From 9700d2487ccb4e043fff10e8fb956fcc2c4a34e4 Mon Sep 17 00:00:00 2001 From: MohammedKHC Date: Sat, 15 Nov 2025 13:40:11 +0200 Subject: [PATCH 1/8] Add androidNative targets. --- build-support/src/main/kotlin/platforms.kt | 13 ++++- okio/build.gradle.kts | 14 ++++- .../kotlin/okio/AndroidNativePosixVariant.kt | 53 +++++++++++++++++++ .../kotlin/okio/ApplePosixVariant.kt | 7 +++ .../kotlin/okio/LinuxPosixVariant.kt | 7 +++ .../kotlin/okio/WindowsPosixVariant.kt | 6 +++ .../nativeMain/kotlin/okio/PosixFileSystem.kt | 10 ++-- .../unixMain/kotlin/okio/UnixFileHandle.kt | 5 +- .../unixMain/kotlin/okio/UnixPosixVariant.kt | 7 +-- 9 files changed, 113 insertions(+), 9 deletions(-) create mode 100644 okio/src/androidNativeMain/kotlin/okio/AndroidNativePosixVariant.kt diff --git a/build-support/src/main/kotlin/platforms.kt b/build-support/src/main/kotlin/platforms.kt index ee233310e2..4783f14048 100644 --- a/build-support/src/main/kotlin/platforms.kt +++ b/build-support/src/main/kotlin/platforms.kt @@ -34,6 +34,10 @@ fun KotlinMultiplatformExtension.configureOrCreateOkioPlatforms() { } fun KotlinMultiplatformExtension.configureOrCreateNativePlatforms() { + androidNativeArm64() + androidNativeArm32() + androidNativeX64() + androidNativeX86() iosX64() iosArm64() iosSimulatorArm64() @@ -53,6 +57,13 @@ fun KotlinMultiplatformExtension.configureOrCreateNativePlatforms() { mingwX64() } +val androidNativeTargets = listOf( + "androidNativeArm64", + "androidNativeArm32", + "androidNativeX64", + "androidNativeX86", +) + val appleTargets = listOf( "iosArm64", "iosX64", @@ -78,7 +89,7 @@ val linuxTargets = listOf( "linuxArm64", ) -val nativeTargets = appleTargets + linuxTargets + mingwTargets +val nativeTargets = androidNativeTargets + appleTargets + linuxTargets + mingwTargets val wasmTargets = listOf( "wasmJs", diff --git a/okio/build.gradle.kts b/okio/build.gradle.kts index fefa201362..7d40ca7885 100644 --- a/okio/build.gradle.kts +++ b/okio/build.gradle.kts @@ -28,6 +28,11 @@ plugins { * | |-- mingw * | | '-- mingwX64 * | '-- unix + * | |-- androidNative + * | | |-- androidNativeArm64 + * | | |-- androidNativeArm32 + * | | |-- androidNativeX64 + * | | |-- androidNativeX86 * | |-- apple * | | |-- iosArm64 * | | |-- iosX64 @@ -163,6 +168,13 @@ kotlin { createSourceSet("unixMain", parent = nativeMain) .also { unixMain -> unixMain.dependsOn(nonJsMain) + createSourceSet( + "androidNativeMain", + parent = unixMain, + children = androidNativeTargets, + ).also { androidNative -> + androidNative.dependsOn(nonAppleMain) + } createSourceSet( "linuxMain", parent = unixMain, @@ -174,7 +186,7 @@ kotlin { } } - createSourceSet("nativeTest", parent = commonTest, children = mingwTargets + linuxTargets) + createSourceSet("nativeTest", parent = commonTest, children = androidNativeTargets + mingwTargets + linuxTargets) .also { nativeTest -> nativeTest.dependsOn(nonJvmTest) nativeTest.dependsOn(nonWasmTest) diff --git a/okio/src/androidNativeMain/kotlin/okio/AndroidNativePosixVariant.kt b/okio/src/androidNativeMain/kotlin/okio/AndroidNativePosixVariant.kt new file mode 100644 index 0000000000..9d3903e026 --- /dev/null +++ b/okio/src/androidNativeMain/kotlin/okio/AndroidNativePosixVariant.kt @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2020 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 + +import kotlinx.cinterop.CValuesRef +import kotlinx.cinterop.alloc +import kotlinx.cinterop.memScoped +import kotlinx.cinterop.ptr +import platform.posix.ENOENT +import platform.posix.S_IFDIR +import platform.posix.S_IFMT +import platform.posix.S_IFREG +import platform.posix.errno +import platform.posix.lstat +import platform.posix.stat + +internal actual fun PosixFileSystem.variantMetadataOrNull(path: Path): FileMetadata? { + return memScoped { + val stat = alloc() + if (lstat(path.toString(), stat.ptr) != 0) { + if (errno == ENOENT) return null + throw errnoToIOException(errno) + } + return@memScoped FileMetadata( + isRegularFile = stat.st_mode.toInt() and S_IFMT == S_IFREG, + isDirectory = stat.st_mode.toInt() and S_IFMT == S_IFDIR, + symlinkTarget = symlinkTarget(stat, path), + size = stat.st_size, + createdAtMillis = stat.st_ctim.epochMillis, + lastModifiedAtMillis = stat.st_mtim.epochMillis, + lastAccessedAtMillis = stat.st_atim.epochMillis, + ) + } +} + +internal actual val DEFFILEMODE: Int get() = 0b110110110 /* octal 666 */ +internal actual typealias DIR = cnames.structs.DIR +internal actual fun opendir(path: String) = platform.posix.opendir(path) +internal actual fun readdir(dir: CValuesRef) = platform.posix.readdir(dir) +internal actual fun closedir(dir: CValuesRef) = platform.posix.closedir(dir) diff --git a/okio/src/appleMain/kotlin/okio/ApplePosixVariant.kt b/okio/src/appleMain/kotlin/okio/ApplePosixVariant.kt index 8840180bc0..53e9179280 100644 --- a/okio/src/appleMain/kotlin/okio/ApplePosixVariant.kt +++ b/okio/src/appleMain/kotlin/okio/ApplePosixVariant.kt @@ -15,6 +15,7 @@ */ package okio +import kotlinx.cinterop.CValuesRef import kotlinx.cinterop.alloc import kotlinx.cinterop.memScoped import kotlinx.cinterop.ptr @@ -44,3 +45,9 @@ internal actual fun PosixFileSystem.variantMetadataOrNull(path: Path): FileMetad ) } } + +internal actual val DEFFILEMODE: Int get() = platform.posix.DEFFILEMODE +internal actual typealias DIR = platform.posix.DIR +internal actual fun opendir(path: String) = platform.posix.opendir(path) +internal actual fun readdir(dir: CValuesRef) = platform.posix.readdir(dir) +internal actual fun closedir(dir: CValuesRef) = platform.posix.closedir(dir) diff --git a/okio/src/linuxMain/kotlin/okio/LinuxPosixVariant.kt b/okio/src/linuxMain/kotlin/okio/LinuxPosixVariant.kt index 168d0ddc11..23722c5e41 100644 --- a/okio/src/linuxMain/kotlin/okio/LinuxPosixVariant.kt +++ b/okio/src/linuxMain/kotlin/okio/LinuxPosixVariant.kt @@ -15,6 +15,7 @@ */ package okio +import kotlinx.cinterop.CValuesRef import kotlinx.cinterop.alloc import kotlinx.cinterop.memScoped import kotlinx.cinterop.ptr @@ -44,3 +45,9 @@ internal actual fun PosixFileSystem.variantMetadataOrNull(path: Path): FileMetad ) } } + +internal actual val DEFFILEMODE: Int get() = platform.posix.DEFFILEMODE +internal actual typealias DIR = cnames.structs.__dirstream +internal actual fun opendir(path: String) = platform.posix.opendir(path) +internal actual fun readdir(dir: CValuesRef) = platform.posix.readdir(dir) +internal actual fun closedir(dir: CValuesRef) = platform.posix.closedir(dir) diff --git a/okio/src/mingwX64Main/kotlin/okio/WindowsPosixVariant.kt b/okio/src/mingwX64Main/kotlin/okio/WindowsPosixVariant.kt index 21dd41a07a..98cba3056f 100644 --- a/okio/src/mingwX64Main/kotlin/okio/WindowsPosixVariant.kt +++ b/okio/src/mingwX64Main/kotlin/okio/WindowsPosixVariant.kt @@ -16,6 +16,7 @@ package okio import kotlinx.cinterop.CPointer +import kotlinx.cinterop.CValuesRef import kotlinx.cinterop.alloc import kotlinx.cinterop.memScoped import kotlinx.cinterop.ptr @@ -204,3 +205,8 @@ internal actual fun PosixFileSystem.variantOpenReadWrite( internal actual fun PosixFileSystem.variantCreateSymlink(source: Path, target: Path) { throw IOException("Not supported") } + +internal actual typealias DIR = platform.posix.DIR +internal actual fun opendir(path: String) = platform.posix.opendir(path) +internal actual fun readdir(dir: CValuesRef) = platform.posix.readdir(dir) +internal actual fun closedir(dir: CValuesRef) = platform.posix.closedir(dir) diff --git a/okio/src/nativeMain/kotlin/okio/PosixFileSystem.kt b/okio/src/nativeMain/kotlin/okio/PosixFileSystem.kt index ecd2b97ac7..a520f59d89 100644 --- a/okio/src/nativeMain/kotlin/okio/PosixFileSystem.kt +++ b/okio/src/nativeMain/kotlin/okio/PosixFileSystem.kt @@ -15,16 +15,15 @@ */ package okio +import kotlinx.cinterop.CPointed import kotlinx.cinterop.CPointer +import kotlinx.cinterop.CValuesRef import kotlinx.cinterop.get import okio.Path.Companion.toPath 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() { @@ -117,3 +116,8 @@ internal object PosixFileSystem : FileSystem() { override fun toString() = "PosixSystemFileSystem" } + +internal expect class DIR : CPointed +internal expect fun opendir(path: String): CPointer? +internal expect fun readdir(dir: CValuesRef): CPointer? +internal expect fun closedir(dir: CValuesRef): Int diff --git a/okio/src/unixMain/kotlin/okio/UnixFileHandle.kt b/okio/src/unixMain/kotlin/okio/UnixFileHandle.kt index 62e7849f7e..7f57bdd5f1 100644 --- a/okio/src/unixMain/kotlin/okio/UnixFileHandle.kt +++ b/okio/src/unixMain/kotlin/okio/UnixFileHandle.kt @@ -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 @@ -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) } } diff --git a/okio/src/unixMain/kotlin/okio/UnixPosixVariant.kt b/okio/src/unixMain/kotlin/okio/UnixPosixVariant.kt index 27630d6775..f61f39b3d3 100644 --- a/okio/src/unixMain/kotlin/okio/UnixPosixVariant.kt +++ b/okio/src/unixMain/kotlin/okio/UnixPosixVariant.kt @@ -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 @@ -130,6 +129,8 @@ internal actual fun PosixFileSystem.variantOpenReadOnly(file: Path): FileHandle return UnixFileHandle(false, openFile) } +internal expect val DEFFILEMODE: Int + internal actual fun PosixFileSystem.variantOpenReadWrite( file: Path, mustCreate: Boolean, @@ -176,7 +177,7 @@ 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( @@ -184,7 +185,7 @@ internal fun variantPwrite( 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 From 1245ccf7af2bc27dcba10ed5b4a211b9195403cd Mon Sep 17 00:00:00 2001 From: MohammedKHC Date: Sat, 7 Feb 2026 16:08:51 +0200 Subject: [PATCH 2/8] Make Android Native a child of Linux. and workaround `platform.posix.DIR` not being available there. --- okio/build.gradle.kts | 20 +++---- .../kotlin/okio/AndroidNativePosixVariant.kt | 53 ------------------- .../kotlin/platform/posix/DIR.kt | 21 ++++++++ .../kotlin/okio/ApplePosixVariant.kt | 7 --- .../kotlin/okio/LinuxPosixVariant.kt | 7 --- .../kotlin/okio/WindowsPosixVariant.kt | 6 --- .../nativeMain/kotlin/okio/PosixFileSystem.kt | 10 ++-- .../unixMain/kotlin/okio/UnixPosixVariant.kt | 2 +- 8 files changed, 32 insertions(+), 94 deletions(-) delete mode 100644 okio/src/androidNativeMain/kotlin/okio/AndroidNativePosixVariant.kt create mode 100644 okio/src/androidNativeMain/kotlin/platform/posix/DIR.kt diff --git a/okio/build.gradle.kts b/okio/build.gradle.kts index 7d40ca7885..57ad6f5c8b 100644 --- a/okio/build.gradle.kts +++ b/okio/build.gradle.kts @@ -28,11 +28,6 @@ plugins { * | |-- mingw * | | '-- mingwX64 * | '-- unix - * | |-- androidNative - * | | |-- androidNativeArm64 - * | | |-- androidNativeArm32 - * | | |-- androidNativeX64 - * | | |-- androidNativeX86 * | |-- apple * | | |-- iosArm64 * | | |-- iosX64 @@ -43,7 +38,12 @@ plugins { * | | |-- watchosArm64 * | '-- linux * | |-- linuxX64 - * | '-- linuxArm64 + * | |-- linuxArm64 + * | '-- androidNative + * | |-- androidNativeArm64 + * | |-- androidNativeArm32 + * | |-- androidNativeX64 + * | |-- androidNativeX86 * '-- wasm * '-- wasmJs * '-- wasmWasi @@ -168,19 +168,13 @@ kotlin { createSourceSet("unixMain", parent = nativeMain) .also { unixMain -> unixMain.dependsOn(nonJsMain) - createSourceSet( - "androidNativeMain", - parent = unixMain, - children = androidNativeTargets, - ).also { androidNative -> - androidNative.dependsOn(nonAppleMain) - } createSourceSet( "linuxMain", parent = unixMain, children = linuxTargets, ).also { linuxMain -> linuxMain.dependsOn(nonAppleMain) + createSourceSet("androidNativeMain", parent = linuxMain, children = androidNativeTargets) } createSourceSet("appleMain", parent = unixMain, children = appleTargets) } diff --git a/okio/src/androidNativeMain/kotlin/okio/AndroidNativePosixVariant.kt b/okio/src/androidNativeMain/kotlin/okio/AndroidNativePosixVariant.kt deleted file mode 100644 index 9d3903e026..0000000000 --- a/okio/src/androidNativeMain/kotlin/okio/AndroidNativePosixVariant.kt +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2020 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 - -import kotlinx.cinterop.CValuesRef -import kotlinx.cinterop.alloc -import kotlinx.cinterop.memScoped -import kotlinx.cinterop.ptr -import platform.posix.ENOENT -import platform.posix.S_IFDIR -import platform.posix.S_IFMT -import platform.posix.S_IFREG -import platform.posix.errno -import platform.posix.lstat -import platform.posix.stat - -internal actual fun PosixFileSystem.variantMetadataOrNull(path: Path): FileMetadata? { - return memScoped { - val stat = alloc() - if (lstat(path.toString(), stat.ptr) != 0) { - if (errno == ENOENT) return null - throw errnoToIOException(errno) - } - return@memScoped FileMetadata( - isRegularFile = stat.st_mode.toInt() and S_IFMT == S_IFREG, - isDirectory = stat.st_mode.toInt() and S_IFMT == S_IFDIR, - symlinkTarget = symlinkTarget(stat, path), - size = stat.st_size, - createdAtMillis = stat.st_ctim.epochMillis, - lastModifiedAtMillis = stat.st_mtim.epochMillis, - lastAccessedAtMillis = stat.st_atim.epochMillis, - ) - } -} - -internal actual val DEFFILEMODE: Int get() = 0b110110110 /* octal 666 */ -internal actual typealias DIR = cnames.structs.DIR -internal actual fun opendir(path: String) = platform.posix.opendir(path) -internal actual fun readdir(dir: CValuesRef) = platform.posix.readdir(dir) -internal actual fun closedir(dir: CValuesRef) = platform.posix.closedir(dir) diff --git a/okio/src/androidNativeMain/kotlin/platform/posix/DIR.kt b/okio/src/androidNativeMain/kotlin/platform/posix/DIR.kt new file mode 100644 index 0000000000..f16c2821b4 --- /dev/null +++ b/okio/src/androidNativeMain/kotlin/platform/posix/DIR.kt @@ -0,0 +1,21 @@ +/* + * 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 platform.posix + +/** + * Workaround `platform.posix.DIR` not being available on Android Native. + */ +internal typealias DIR = cnames.structs.DIR diff --git a/okio/src/appleMain/kotlin/okio/ApplePosixVariant.kt b/okio/src/appleMain/kotlin/okio/ApplePosixVariant.kt index 53e9179280..8840180bc0 100644 --- a/okio/src/appleMain/kotlin/okio/ApplePosixVariant.kt +++ b/okio/src/appleMain/kotlin/okio/ApplePosixVariant.kt @@ -15,7 +15,6 @@ */ package okio -import kotlinx.cinterop.CValuesRef import kotlinx.cinterop.alloc import kotlinx.cinterop.memScoped import kotlinx.cinterop.ptr @@ -45,9 +44,3 @@ internal actual fun PosixFileSystem.variantMetadataOrNull(path: Path): FileMetad ) } } - -internal actual val DEFFILEMODE: Int get() = platform.posix.DEFFILEMODE -internal actual typealias DIR = platform.posix.DIR -internal actual fun opendir(path: String) = platform.posix.opendir(path) -internal actual fun readdir(dir: CValuesRef) = platform.posix.readdir(dir) -internal actual fun closedir(dir: CValuesRef) = platform.posix.closedir(dir) diff --git a/okio/src/linuxMain/kotlin/okio/LinuxPosixVariant.kt b/okio/src/linuxMain/kotlin/okio/LinuxPosixVariant.kt index 23722c5e41..168d0ddc11 100644 --- a/okio/src/linuxMain/kotlin/okio/LinuxPosixVariant.kt +++ b/okio/src/linuxMain/kotlin/okio/LinuxPosixVariant.kt @@ -15,7 +15,6 @@ */ package okio -import kotlinx.cinterop.CValuesRef import kotlinx.cinterop.alloc import kotlinx.cinterop.memScoped import kotlinx.cinterop.ptr @@ -45,9 +44,3 @@ internal actual fun PosixFileSystem.variantMetadataOrNull(path: Path): FileMetad ) } } - -internal actual val DEFFILEMODE: Int get() = platform.posix.DEFFILEMODE -internal actual typealias DIR = cnames.structs.__dirstream -internal actual fun opendir(path: String) = platform.posix.opendir(path) -internal actual fun readdir(dir: CValuesRef) = platform.posix.readdir(dir) -internal actual fun closedir(dir: CValuesRef) = platform.posix.closedir(dir) diff --git a/okio/src/mingwX64Main/kotlin/okio/WindowsPosixVariant.kt b/okio/src/mingwX64Main/kotlin/okio/WindowsPosixVariant.kt index 98cba3056f..21dd41a07a 100644 --- a/okio/src/mingwX64Main/kotlin/okio/WindowsPosixVariant.kt +++ b/okio/src/mingwX64Main/kotlin/okio/WindowsPosixVariant.kt @@ -16,7 +16,6 @@ package okio import kotlinx.cinterop.CPointer -import kotlinx.cinterop.CValuesRef import kotlinx.cinterop.alloc import kotlinx.cinterop.memScoped import kotlinx.cinterop.ptr @@ -205,8 +204,3 @@ internal actual fun PosixFileSystem.variantOpenReadWrite( internal actual fun PosixFileSystem.variantCreateSymlink(source: Path, target: Path) { throw IOException("Not supported") } - -internal actual typealias DIR = platform.posix.DIR -internal actual fun opendir(path: String) = platform.posix.opendir(path) -internal actual fun readdir(dir: CValuesRef) = platform.posix.readdir(dir) -internal actual fun closedir(dir: CValuesRef) = platform.posix.closedir(dir) diff --git a/okio/src/nativeMain/kotlin/okio/PosixFileSystem.kt b/okio/src/nativeMain/kotlin/okio/PosixFileSystem.kt index a520f59d89..ecd2b97ac7 100644 --- a/okio/src/nativeMain/kotlin/okio/PosixFileSystem.kt +++ b/okio/src/nativeMain/kotlin/okio/PosixFileSystem.kt @@ -15,15 +15,16 @@ */ package okio -import kotlinx.cinterop.CPointed import kotlinx.cinterop.CPointer -import kotlinx.cinterop.CValuesRef import kotlinx.cinterop.get import okio.Path.Companion.toPath 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() { @@ -116,8 +117,3 @@ internal object PosixFileSystem : FileSystem() { override fun toString() = "PosixSystemFileSystem" } - -internal expect class DIR : CPointed -internal expect fun opendir(path: String): CPointer? -internal expect fun readdir(dir: CValuesRef): CPointer? -internal expect fun closedir(dir: CValuesRef): Int diff --git a/okio/src/unixMain/kotlin/okio/UnixPosixVariant.kt b/okio/src/unixMain/kotlin/okio/UnixPosixVariant.kt index f61f39b3d3..2071c7601a 100644 --- a/okio/src/unixMain/kotlin/okio/UnixPosixVariant.kt +++ b/okio/src/unixMain/kotlin/okio/UnixPosixVariant.kt @@ -129,7 +129,7 @@ internal actual fun PosixFileSystem.variantOpenReadOnly(file: Path): FileHandle return UnixFileHandle(false, openFile) } -internal expect val DEFFILEMODE: Int +internal const val DEFFILEMODE = 0b110110110 /* octal 666 */ internal actual fun PosixFileSystem.variantOpenReadWrite( file: Path, From 6a1fca7faa27865c7e52c50e0fa3bd94dec6b341 Mon Sep 17 00:00:00 2001 From: MohammedKHC Date: Mon, 9 Feb 2026 13:07:06 +0200 Subject: [PATCH 3/8] Add Android Native support for opendir/readdir/closedir. --- okio/build.gradle.kts | 2 ++ .../{platform/posix => okio/internal}/DIR.kt | 12 ++++--- .../nativeMain/kotlin/okio/PosixFileSystem.kt | 6 ++-- .../nativeMain/kotlin/okio/internal/DIR.kt | 34 +++++++++++++++++++ .../kotlin/okio/internal/DIR.kt | 23 +++++++++++++ 5 files changed, 69 insertions(+), 8 deletions(-) rename okio/src/androidNativeMain/kotlin/{platform/posix => okio/internal}/DIR.kt (63%) create mode 100644 okio/src/nativeMain/kotlin/okio/internal/DIR.kt create mode 100644 okio/src/nativeNonAndroidMain/kotlin/okio/internal/DIR.kt diff --git a/okio/build.gradle.kts b/okio/build.gradle.kts index 57ad6f5c8b..47227b6d52 100644 --- a/okio/build.gradle.kts +++ b/okio/build.gradle.kts @@ -178,6 +178,8 @@ kotlin { } createSourceSet("appleMain", parent = unixMain, children = appleTargets) } + + createSourceSet("nativeNonAndroidMain", parent = nativeMain, children = appleTargets + mingwTargets + linuxTargets) } createSourceSet("nativeTest", parent = commonTest, children = androidNativeTargets + mingwTargets + linuxTargets) diff --git a/okio/src/androidNativeMain/kotlin/platform/posix/DIR.kt b/okio/src/androidNativeMain/kotlin/okio/internal/DIR.kt similarity index 63% rename from okio/src/androidNativeMain/kotlin/platform/posix/DIR.kt rename to okio/src/androidNativeMain/kotlin/okio/internal/DIR.kt index f16c2821b4..1e97b3c4f2 100644 --- a/okio/src/androidNativeMain/kotlin/platform/posix/DIR.kt +++ b/okio/src/androidNativeMain/kotlin/okio/internal/DIR.kt @@ -13,9 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package platform.posix +package okio.internal -/** - * Workaround `platform.posix.DIR` not being available on Android Native. - */ -internal typealias DIR = cnames.structs.DIR +import kotlinx.cinterop.CValuesRef + +internal actual typealias DIR = cnames.structs.DIR +internal actual fun opendir(path: String) = platform.posix.opendir(path) +internal actual fun readdir(dir: CValuesRef) = platform.posix.readdir(dir) +internal actual fun closedir(dir: CValuesRef) = platform.posix.closedir(dir) diff --git a/okio/src/nativeMain/kotlin/okio/PosixFileSystem.kt b/okio/src/nativeMain/kotlin/okio/PosixFileSystem.kt index ecd2b97ac7..fdd8fab4d9 100644 --- a/okio/src/nativeMain/kotlin/okio/PosixFileSystem.kt +++ b/okio/src/nativeMain/kotlin/okio/PosixFileSystem.kt @@ -18,13 +18,13 @@ package okio import kotlinx.cinterop.CPointer import kotlinx.cinterop.get import okio.Path.Companion.toPath +import okio.internal.closedir +import okio.internal.opendir +import okio.internal.readdir 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() { diff --git a/okio/src/nativeMain/kotlin/okio/internal/DIR.kt b/okio/src/nativeMain/kotlin/okio/internal/DIR.kt new file mode 100644 index 0000000000..4ae61c3595 --- /dev/null +++ b/okio/src/nativeMain/kotlin/okio/internal/DIR.kt @@ -0,0 +1,34 @@ +/* + * 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.CPointed +import kotlinx.cinterop.CPointer +import kotlinx.cinterop.CValuesRef +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. + * + * These expect declarations provide platform-specific implementations + * for all `DIR`-related functionality. + */ +internal expect class DIR : CPointed +internal expect fun opendir(path: String): CPointer? +internal expect fun readdir(dir: CValuesRef): CPointer? +internal expect fun closedir(dir: CValuesRef): Int diff --git a/okio/src/nativeNonAndroidMain/kotlin/okio/internal/DIR.kt b/okio/src/nativeNonAndroidMain/kotlin/okio/internal/DIR.kt new file mode 100644 index 0000000000..4897b898fb --- /dev/null +++ b/okio/src/nativeNonAndroidMain/kotlin/okio/internal/DIR.kt @@ -0,0 +1,23 @@ +/* + * 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.CValuesRef + +internal actual typealias DIR = platform.posix.DIR +internal actual fun opendir(path: String) = platform.posix.opendir(path) +internal actual fun readdir(dir: CValuesRef) = platform.posix.readdir(dir) +internal actual fun closedir(dir: CValuesRef) = platform.posix.closedir(dir) From 8aabd6d1ca370bcf29be3664a544de1dc7b99799 Mon Sep 17 00:00:00 2001 From: MohammedKHC Date: Mon, 9 Feb 2026 13:55:10 +0200 Subject: [PATCH 4/8] Add `PosixDirectory` and use it instead of expect/actual `DIR` functions. Unfortunately we cannot typealias `DIR` in a shared source set. Because it is already a typealias on Linux. --- .../internal/{DIR.kt => PosixDirectory.kt} | 18 +++++++++++++----- .../nativeMain/kotlin/okio/PosixFileSystem.kt | 19 +++++++------------ .../internal/{DIR.kt => PosixDirectory.kt} | 17 +++++++++-------- .../internal/{DIR.kt => PosixDirectory.kt} | 18 +++++++++++++----- 4 files changed, 42 insertions(+), 30 deletions(-) rename okio/src/androidNativeMain/kotlin/okio/internal/{DIR.kt => PosixDirectory.kt} (59%) rename okio/src/nativeMain/kotlin/okio/internal/{DIR.kt => PosixDirectory.kt} (68%) rename okio/src/nativeNonAndroidMain/kotlin/okio/internal/{DIR.kt => PosixDirectory.kt} (59%) diff --git a/okio/src/androidNativeMain/kotlin/okio/internal/DIR.kt b/okio/src/androidNativeMain/kotlin/okio/internal/PosixDirectory.kt similarity index 59% rename from okio/src/androidNativeMain/kotlin/okio/internal/DIR.kt rename to okio/src/androidNativeMain/kotlin/okio/internal/PosixDirectory.kt index 1e97b3c4f2..0f6ad5de02 100644 --- a/okio/src/androidNativeMain/kotlin/okio/internal/DIR.kt +++ b/okio/src/androidNativeMain/kotlin/okio/internal/PosixDirectory.kt @@ -15,9 +15,17 @@ */ package okio.internal -import kotlinx.cinterop.CValuesRef +import okio.Closeable +import okio.Path +import platform.posix.closedir +import platform.posix.opendir +import platform.posix.readdir -internal actual typealias DIR = cnames.structs.DIR -internal actual fun opendir(path: String) = platform.posix.opendir(path) -internal actual fun readdir(dir: CValuesRef) = platform.posix.readdir(dir) -internal actual fun closedir(dir: CValuesRef) = platform.posix.closedir(dir) +internal actual class PosixDirectory actual constructor(path: Path) : Closeable { + private val dir = opendir(path.toString()) + actual val isInvalid get() = dir == null + actual fun nextEntry() = readdir(dir) + actual override fun close() { + closedir(dir) // Ignore errno from closedir. + } +} diff --git a/okio/src/nativeMain/kotlin/okio/PosixFileSystem.kt b/okio/src/nativeMain/kotlin/okio/PosixFileSystem.kt index fdd8fab4d9..6690cea21f 100644 --- a/okio/src/nativeMain/kotlin/okio/PosixFileSystem.kt +++ b/okio/src/nativeMain/kotlin/okio/PosixFileSystem.kt @@ -15,15 +15,11 @@ */ package okio -import kotlinx.cinterop.CPointer import kotlinx.cinterop.get import okio.Path.Companion.toPath -import okio.internal.closedir -import okio.internal.opendir -import okio.internal.readdir +import okio.internal.PosixDirectory import okio.internal.toPath import platform.posix.EEXIST -import platform.posix.dirent import platform.posix.errno import platform.posix.set_posix_errno @@ -40,16 +36,17 @@ internal object PosixFileSystem : FileSystem() { override fun listOrNull(dir: Path): List? = list(dir, throwOnFailure = false) private fun list(dir: Path, throwOnFailure: Boolean): List? { - val opendir = opendir(dir.toString()) - ?: if (throwOnFailure) throw errnoToIOException(errno) else return null - - try { + val posixDir = PosixDirectory(dir) + if (posixDir.isInvalid) { + if (throwOnFailure) throw errnoToIOException(errno) else return null + } + posixDir.use { val result = mutableListOf() val buffer = Buffer() set_posix_errno(0) // If readdir() returns null it's either the end or an error. while (true) { - val dirent: CPointer = readdir(opendir) ?: break + val dirent = it.nextEntry() ?: break val childPath = buffer.writeNullTerminated( bytes = dirent[0].d_name, ).toPath(normalize = true) @@ -71,8 +68,6 @@ internal object PosixFileSystem : FileSystem() { result.sort() return result - } finally { - closedir(opendir) // Ignore errno from closedir. } } diff --git a/okio/src/nativeMain/kotlin/okio/internal/DIR.kt b/okio/src/nativeMain/kotlin/okio/internal/PosixDirectory.kt similarity index 68% rename from okio/src/nativeMain/kotlin/okio/internal/DIR.kt rename to okio/src/nativeMain/kotlin/okio/internal/PosixDirectory.kt index 4ae61c3595..f97a2acb80 100644 --- a/okio/src/nativeMain/kotlin/okio/internal/DIR.kt +++ b/okio/src/nativeMain/kotlin/okio/internal/PosixDirectory.kt @@ -15,9 +15,9 @@ */ package okio.internal -import kotlinx.cinterop.CPointed import kotlinx.cinterop.CPointer -import kotlinx.cinterop.CValuesRef +import okio.Closeable +import okio.Path import platform.posix.dirent /** @@ -25,10 +25,11 @@ import platform.posix.dirent * POSIX directory APIs (`opendir`, `readdir`, `closedir`) cannot be used * directly. * - * These expect declarations provide platform-specific implementations - * for all `DIR`-related functionality. + * [PosixDirectory] provides platform-specific implementation + * for `DIR`-related functionality. */ -internal expect class DIR : CPointed -internal expect fun opendir(path: String): CPointer? -internal expect fun readdir(dir: CValuesRef): CPointer? -internal expect fun closedir(dir: CValuesRef): Int +internal expect class PosixDirectory(path: Path) : Closeable { + val isInvalid: Boolean + fun nextEntry(): CPointer? + override fun close() +} diff --git a/okio/src/nativeNonAndroidMain/kotlin/okio/internal/DIR.kt b/okio/src/nativeNonAndroidMain/kotlin/okio/internal/PosixDirectory.kt similarity index 59% rename from okio/src/nativeNonAndroidMain/kotlin/okio/internal/DIR.kt rename to okio/src/nativeNonAndroidMain/kotlin/okio/internal/PosixDirectory.kt index 4897b898fb..0f6ad5de02 100644 --- a/okio/src/nativeNonAndroidMain/kotlin/okio/internal/DIR.kt +++ b/okio/src/nativeNonAndroidMain/kotlin/okio/internal/PosixDirectory.kt @@ -15,9 +15,17 @@ */ package okio.internal -import kotlinx.cinterop.CValuesRef +import okio.Closeable +import okio.Path +import platform.posix.closedir +import platform.posix.opendir +import platform.posix.readdir -internal actual typealias DIR = platform.posix.DIR -internal actual fun opendir(path: String) = platform.posix.opendir(path) -internal actual fun readdir(dir: CValuesRef) = platform.posix.readdir(dir) -internal actual fun closedir(dir: CValuesRef) = platform.posix.closedir(dir) +internal actual class PosixDirectory actual constructor(path: Path) : Closeable { + private val dir = opendir(path.toString()) + actual val isInvalid get() = dir == null + actual fun nextEntry() = readdir(dir) + actual override fun close() { + closedir(dir) // Ignore errno from closedir. + } +} From 44019d6a4eb442cc6f318f8eeab48bd7cc1a6e1e Mon Sep 17 00:00:00 2001 From: MohammedKHC Date: Wed, 11 Feb 2026 07:05:14 +0200 Subject: [PATCH 5/8] Use value class for `PosixDirectory`. --- .../kotlin/okio/internal/PosixDirectory.kt | 14 +++++++++----- okio/src/nativeMain/kotlin/okio/PosixFileSystem.kt | 8 +++----- .../kotlin/okio/internal/PosixDirectory.kt | 6 ++++-- .../kotlin/okio/internal/PosixDirectory.kt | 14 +++++++++----- 4 files changed, 25 insertions(+), 17 deletions(-) diff --git a/okio/src/androidNativeMain/kotlin/okio/internal/PosixDirectory.kt b/okio/src/androidNativeMain/kotlin/okio/internal/PosixDirectory.kt index 0f6ad5de02..7af623d1f9 100644 --- a/okio/src/androidNativeMain/kotlin/okio/internal/PosixDirectory.kt +++ b/okio/src/androidNativeMain/kotlin/okio/internal/PosixDirectory.kt @@ -15,17 +15,21 @@ */ 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 class PosixDirectory actual constructor(path: Path) : Closeable { - private val dir = opendir(path.toString()) - actual val isInvalid get() = dir == null - actual fun nextEntry() = readdir(dir) +internal actual value class PosixDirectory(private val dir: COpaquePointer) : Closeable { + actual fun nextEntry() = readdir(dir.reinterpret()) actual override fun close() { - closedir(dir) // Ignore errno from closedir. + closedir(dir.reinterpret()) // Ignore errno from closedir. } } + +internal actual fun openPosixDirectory(path: Path): PosixDirectory? { + return opendir(path.toString())?.let(::PosixDirectory) +} diff --git a/okio/src/nativeMain/kotlin/okio/PosixFileSystem.kt b/okio/src/nativeMain/kotlin/okio/PosixFileSystem.kt index 6690cea21f..d7512f2954 100644 --- a/okio/src/nativeMain/kotlin/okio/PosixFileSystem.kt +++ b/okio/src/nativeMain/kotlin/okio/PosixFileSystem.kt @@ -17,7 +17,7 @@ package okio import kotlinx.cinterop.get import okio.Path.Companion.toPath -import okio.internal.PosixDirectory +import okio.internal.openPosixDirectory import okio.internal.toPath import platform.posix.EEXIST import platform.posix.errno @@ -36,10 +36,8 @@ internal object PosixFileSystem : FileSystem() { override fun listOrNull(dir: Path): List? = list(dir, throwOnFailure = false) private fun list(dir: Path, throwOnFailure: Boolean): List? { - val posixDir = PosixDirectory(dir) - if (posixDir.isInvalid) { - if (throwOnFailure) throw errnoToIOException(errno) else return null - } + val posixDir = openPosixDirectory(dir) + ?: if (throwOnFailure) throw errnoToIOException(errno) else return null posixDir.use { val result = mutableListOf() val buffer = Buffer() diff --git a/okio/src/nativeMain/kotlin/okio/internal/PosixDirectory.kt b/okio/src/nativeMain/kotlin/okio/internal/PosixDirectory.kt index f97a2acb80..31ad141cd2 100644 --- a/okio/src/nativeMain/kotlin/okio/internal/PosixDirectory.kt +++ b/okio/src/nativeMain/kotlin/okio/internal/PosixDirectory.kt @@ -15,6 +15,7 @@ */ package okio.internal +import kotlinx.cinterop.COpaquePointer import kotlinx.cinterop.CPointer import okio.Closeable import okio.Path @@ -28,8 +29,9 @@ import platform.posix.dirent * [PosixDirectory] provides platform-specific implementation * for `DIR`-related functionality. */ -internal expect class PosixDirectory(path: Path) : Closeable { - val isInvalid: Boolean +internal expect value class PosixDirectory(private val dir: COpaquePointer) : Closeable { fun nextEntry(): CPointer? override fun close() } + +internal expect fun openPosixDirectory(path: Path): PosixDirectory? diff --git a/okio/src/nativeNonAndroidMain/kotlin/okio/internal/PosixDirectory.kt b/okio/src/nativeNonAndroidMain/kotlin/okio/internal/PosixDirectory.kt index 0f6ad5de02..7af623d1f9 100644 --- a/okio/src/nativeNonAndroidMain/kotlin/okio/internal/PosixDirectory.kt +++ b/okio/src/nativeNonAndroidMain/kotlin/okio/internal/PosixDirectory.kt @@ -15,17 +15,21 @@ */ 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 class PosixDirectory actual constructor(path: Path) : Closeable { - private val dir = opendir(path.toString()) - actual val isInvalid get() = dir == null - actual fun nextEntry() = readdir(dir) +internal actual value class PosixDirectory(private val dir: COpaquePointer) : Closeable { + actual fun nextEntry() = readdir(dir.reinterpret()) actual override fun close() { - closedir(dir) // Ignore errno from closedir. + closedir(dir.reinterpret()) // Ignore errno from closedir. } } + +internal actual fun openPosixDirectory(path: Path): PosixDirectory? { + return opendir(path.toString())?.let(::PosixDirectory) +} From 307b25d378eea05d5da272d8d58282ad9733c530 Mon Sep 17 00:00:00 2001 From: MohammedKHC Date: Sat, 14 Mar 2026 05:20:34 +0200 Subject: [PATCH 6/8] Use statx on Android native. --- okio/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/okio/build.gradle.kts b/okio/build.gradle.kts index 6d92060ef6..f21e5c0e4b 100644 --- a/okio/build.gradle.kts +++ b/okio/build.gradle.kts @@ -218,7 +218,7 @@ kotlin { } targets.withType { - if (konanTarget.family == Family.LINUX) { + if (konanTarget.family == Family.LINUX || konanTarget.family == Family.ANDROID) { compilations["main"].cinterops.create("linux") { packageName("okio.internal.linux") headers( From d2f842155840b63f9e5f3c7f933f12055cda44f2 Mon Sep 17 00:00:00 2001 From: MohammedKHC Date: Sat, 14 Mar 2026 05:32:12 +0200 Subject: [PATCH 7/8] Inline openPosixDirectory --- .../androidNativeMain/kotlin/okio/internal/PosixDirectory.kt | 3 ++- .../kotlin/okio/internal/PosixDirectory.kt | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/okio/src/androidNativeMain/kotlin/okio/internal/PosixDirectory.kt b/okio/src/androidNativeMain/kotlin/okio/internal/PosixDirectory.kt index 7af623d1f9..6da1e6f318 100644 --- a/okio/src/androidNativeMain/kotlin/okio/internal/PosixDirectory.kt +++ b/okio/src/androidNativeMain/kotlin/okio/internal/PosixDirectory.kt @@ -30,6 +30,7 @@ internal actual value class PosixDirectory(private val dir: COpaquePointer) : Cl } } -internal actual fun openPosixDirectory(path: Path): PosixDirectory? { +@Suppress("NOTHING_TO_INLINE") +internal actual inline fun openPosixDirectory(path: Path): PosixDirectory? { return opendir(path.toString())?.let(::PosixDirectory) } diff --git a/okio/src/nativeNonAndroidMain/kotlin/okio/internal/PosixDirectory.kt b/okio/src/nativeNonAndroidMain/kotlin/okio/internal/PosixDirectory.kt index 7af623d1f9..6da1e6f318 100644 --- a/okio/src/nativeNonAndroidMain/kotlin/okio/internal/PosixDirectory.kt +++ b/okio/src/nativeNonAndroidMain/kotlin/okio/internal/PosixDirectory.kt @@ -30,6 +30,7 @@ internal actual value class PosixDirectory(private val dir: COpaquePointer) : Cl } } -internal actual fun openPosixDirectory(path: Path): PosixDirectory? { +@Suppress("NOTHING_TO_INLINE") +internal actual inline fun openPosixDirectory(path: Path): PosixDirectory? { return opendir(path.toString())?.let(::PosixDirectory) } From dfef41683a7a23c63bb88d277323a2a873831118 Mon Sep 17 00:00:00 2001 From: Mohammed Khaled Date: Fri, 24 Apr 2026 01:09:52 +0000 Subject: [PATCH 8/8] Fix statx syscall for arm32 --- okio/src/linuxMain/kotlin/okio/LinuxPosixVariant.kt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/okio/src/linuxMain/kotlin/okio/LinuxPosixVariant.kt b/okio/src/linuxMain/kotlin/okio/LinuxPosixVariant.kt index 4fdd049d59..bd54512cba 100644 --- a/okio/src/linuxMain/kotlin/okio/LinuxPosixVariant.kt +++ b/okio/src/linuxMain/kotlin/okio/LinuxPosixVariant.kt @@ -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 @@ -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() 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() + 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,