Skip to content
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion build-support/src/main/kotlin/platforms.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ fun KotlinMultiplatformExtension.configureOrCreateOkioPlatforms() {
}

fun KotlinMultiplatformExtension.configureOrCreateNativePlatforms() {
androidNativeArm64()
androidNativeArm32()
androidNativeX64()
androidNativeX86()
iosX64()
iosArm64()
iosSimulatorArm64()
Expand All @@ -53,6 +57,13 @@ fun KotlinMultiplatformExtension.configureOrCreateNativePlatforms() {
mingwX64()
}

val androidNativeTargets = listOf(
"androidNativeArm64",
"androidNativeArm32",
"androidNativeX64",
"androidNativeX86",
)

val appleTargets = listOf(
"iosArm64",
"iosX64",
Expand All @@ -78,7 +89,7 @@ val linuxTargets = listOf(
"linuxArm64",
)

val nativeTargets = appleTargets + linuxTargets + mingwTargets
val nativeTargets = androidNativeTargets + appleTargets + linuxTargets + mingwTargets

val wasmTargets = listOf(
"wasmJs",
Expand Down
14 changes: 11 additions & 3 deletions okio/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,12 @@ plugins {
* | | |-- watchosArm64
* | '-- linux
* | |-- linuxX64
* | '-- linuxArm64
* | |-- linuxArm64
* | '-- androidNative
* | |-- androidNativeArm64
* | |-- androidNativeArm32
* | |-- androidNativeX64
* | |-- androidNativeX86
* '-- wasm
* '-- wasmJs
* '-- wasmWasi
Expand Down Expand Up @@ -171,6 +176,7 @@ kotlin {
children = linuxTargets,
).also { linuxMain ->
linuxMain.dependsOn(nonAppleMain)
createSourceSet("androidNativeMain", parent = linuxMain, children = androidNativeTargets)
}
createSourceSet(
name = "appleMain",
Expand All @@ -184,9 +190,11 @@ kotlin {
)
}
}

createSourceSet("nativeNonAndroidMain", parent = nativeMain, children = appleTargets + mingwTargets + linuxTargets)
}

createSourceSet("nativeTest", parent = commonTest, children = mingwTargets + linuxTargets)
createSourceSet("nativeTest", parent = commonTest, children = androidNativeTargets + mingwTargets + linuxTargets)
.also { nativeTest ->
nativeTest.dependsOn(nonJvmTest)
nativeTest.dependsOn(nonWasmTest)
Expand All @@ -210,7 +218,7 @@ kotlin {
}

targets.withType<KotlinNativeTarget> {
if (konanTarget.family == Family.LINUX) {
if (konanTarget.family == Family.LINUX || konanTarget.family == Family.ANDROID) {
compilations["main"].cinterops.create("linux") {
packageName("okio.internal.linux")
headers(
Expand Down
36 changes: 36 additions & 0 deletions okio/src/androidNativeMain/kotlin/okio/internal/PosixDirectory.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (C) 2026 Square, Inc.
*
* 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 okio.internal

import kotlinx.cinterop.COpaquePointer
import kotlinx.cinterop.reinterpret
import okio.Closeable
import okio.Path
import platform.posix.closedir
import platform.posix.opendir
import platform.posix.readdir

internal actual value class PosixDirectory(private val dir: COpaquePointer) : Closeable {
actual fun nextEntry() = readdir(dir.reinterpret())
actual override fun close() {
closedir(dir.reinterpret()) // Ignore errno from closedir.
}
}

@Suppress("NOTHING_TO_INLINE")
internal actual inline fun openPosixDirectory(path: Path): PosixDirectory? {
return opendir(path.toString())?.let(::PosixDirectory)
}
8 changes: 5 additions & 3 deletions okio/src/linuxMain/kotlin/okio/LinuxPosixVariant.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package okio

import kotlinx.cinterop.UnsafeNumber
import kotlinx.cinterop.alloc
import kotlinx.cinterop.convert
import kotlinx.cinterop.memScoped
import kotlinx.cinterop.ptr
import okio.internal.linux.AT_FDCWD
Expand All @@ -40,18 +41,19 @@ import platform.posix.syscall
* Prefer `statx()` if it's available. Fall back to `stat()` which doesn't have a field for
* `createdAt`.
*/
@OptIn(UnsafeNumber::class)
internal actual fun PosixFileSystem.variantMetadataOrNull(path: Path): FileMetadata? {
memScoped {
val statx = alloc<statx>()
val result = syscall(
__NR_statx.toLong(),
__NR_statx.convert(),
AT_FDCWD,
path.toString(),
AT_SYMLINK_NOFOLLOW,
STATX_BASIC_STATS or STATX_BTIME,
statx.ptr,
)
if (result == 0L) {
).convert<Int>()
if (result == 0) {
return FileMetadata(
isRegularFile = statx.stx_mode.toInt() and S_IFMT == S_IFREG,
isDirectory = statx.stx_mode.toInt() and S_IFMT == S_IFDIR,
Expand Down
15 changes: 4 additions & 11 deletions okio/src/nativeMain/kotlin/okio/PosixFileSystem.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,12 @@
*/
package okio

import kotlinx.cinterop.CPointer
import kotlinx.cinterop.get
import okio.Path.Companion.toPath
import okio.internal.openPosixDirectory
import okio.internal.toPath
import platform.posix.EEXIST
import platform.posix.closedir
import platform.posix.dirent
import platform.posix.errno
import platform.posix.opendir
import platform.posix.readdir
import platform.posix.set_posix_errno

internal object PosixFileSystem : FileSystem() {
Expand All @@ -40,16 +36,15 @@ internal object PosixFileSystem : FileSystem() {
override fun listOrNull(dir: Path): List<Path>? = list(dir, throwOnFailure = false)

private fun list(dir: Path, throwOnFailure: Boolean): List<Path>? {
val opendir = opendir(dir.toString())
val posixDir = openPosixDirectory(dir)
?: if (throwOnFailure) throw errnoToIOException(errno) else return null

try {
posixDir.use {
val result = mutableListOf<Path>()
val buffer = Buffer()

set_posix_errno(0) // If readdir() returns null it's either the end or an error.
while (true) {
val dirent: CPointer<dirent> = readdir(opendir) ?: break
val dirent = it.nextEntry() ?: break
val childPath = buffer.writeNullTerminated(
bytes = dirent[0].d_name,
).toPath(normalize = true)
Expand All @@ -71,8 +66,6 @@ internal object PosixFileSystem : FileSystem() {

result.sort()
return result
} finally {
closedir(opendir) // Ignore errno from closedir.
}
}

Expand Down
37 changes: 37 additions & 0 deletions okio/src/nativeMain/kotlin/okio/internal/PosixDirectory.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright (C) 2026 Square, Inc.
*
* 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 okio.internal

import kotlinx.cinterop.COpaquePointer
import kotlinx.cinterop.CPointer
import okio.Closeable
import okio.Path
import platform.posix.dirent

/**
* `platform.posix.DIR` is not available on Android Native, so the standard
* POSIX directory APIs (`opendir`, `readdir`, `closedir`) cannot be used
* directly.
*
* [PosixDirectory] provides platform-specific implementation
* for `DIR`-related functionality.
*/
internal expect value class PosixDirectory(private val dir: COpaquePointer) : Closeable {
fun nextEntry(): CPointer<dirent>?
override fun close()
}

internal expect fun openPosixDirectory(path: Path): PosixDirectory?
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (C) 2026 Square, Inc.
*
* 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 okio.internal

import kotlinx.cinterop.COpaquePointer
import kotlinx.cinterop.reinterpret
import okio.Closeable
import okio.Path
import platform.posix.closedir
import platform.posix.opendir
import platform.posix.readdir

internal actual value class PosixDirectory(private val dir: COpaquePointer) : Closeable {
actual fun nextEntry() = readdir(dir.reinterpret())
actual override fun close() {
closedir(dir.reinterpret()) // Ignore errno from closedir.
}
}

@Suppress("NOTHING_TO_INLINE")
internal actual inline fun openPosixDirectory(path: Path): PosixDirectory? {
return opendir(path.toString())?.let(::PosixDirectory)
}
5 changes: 4 additions & 1 deletion okio/src/unixMain/kotlin/okio/UnixFileHandle.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@
package okio

import kotlinx.cinterop.CPointer
import kotlinx.cinterop.UnsafeNumber
import kotlinx.cinterop.addressOf
import kotlinx.cinterop.alloc
import kotlinx.cinterop.convert
import kotlinx.cinterop.memScoped
import kotlinx.cinterop.ptr
import kotlinx.cinterop.usePinned
Expand Down Expand Up @@ -84,8 +86,9 @@ internal class UnixFileHandle(
}
}

@OptIn(UnsafeNumber::class)
override fun protectedResize(size: Long) {
if (ftruncate(fileno(file), size) == -1) {
if (ftruncate(fileno(file), size.convert()) == -1) {
throw errnoToIOException(errno)
}
}
Expand Down
7 changes: 4 additions & 3 deletions okio/src/unixMain/kotlin/okio/UnixPosixVariant.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import kotlinx.cinterop.memScoped
import kotlinx.cinterop.toKString
import okio.Path.Companion.toPath
import okio.internal.toPath
import platform.posix.DEFFILEMODE
import platform.posix.ENOENT
import platform.posix.FILE
import platform.posix.O_CREAT
Expand Down Expand Up @@ -129,6 +128,8 @@ internal actual fun PosixFileSystem.variantOpenReadOnly(file: Path): FileHandle
return UnixFileHandle(false, openFile)
}

internal const val DEFFILEMODE = 0b110110110 /* octal 666 */

internal actual fun PosixFileSystem.variantOpenReadWrite(
file: Path,
mustCreate: Boolean,
Expand Down Expand Up @@ -175,15 +176,15 @@ internal fun variantPread(
target: CValuesRef<*>,
byteCount: Int,
offset: Long,
): Int = pread(fileno(file), target, byteCount.convert(), offset).convert()
): Int = pread(fileno(file), target, byteCount.convert(), offset.convert()).convert()

@OptIn(UnsafeNumber::class)
internal fun variantPwrite(
file: CPointer<FILE>,
source: CValuesRef<*>,
byteCount: Int,
offset: Long,
): Int = pwrite(fileno(file), source, byteCount.convert(), offset).convert()
): Int = pwrite(fileno(file), source, byteCount.convert(), offset.convert()).convert()

@OptIn(UnsafeNumber::class)
internal val timespec.epochMillis: Long
Expand Down