From 9700d2487ccb4e043fff10e8fb956fcc2c4a34e4 Mon Sep 17 00:00:00 2001 From: MohammedKHC Date: Sat, 15 Nov 2025 13:40:11 +0200 Subject: [PATCH 01/16] 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 02/16] 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 03/16] 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 04/16] 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 05/16] 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 06/16] 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 07/16] 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 08/16] 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, From 0971aba297f39e622621937b79505e2a8bfa5a0f Mon Sep 17 00:00:00 2001 From: MohammedKHC Date: Fri, 7 Aug 2026 14:14:55 +0300 Subject: [PATCH 09/16] Make `PosixDirectory` an interface. --- okio/build.gradle.kts | 3 +-- .../kotlin/okio/internal/PosixDirectory.kt | 15 +++++++-------- okio/src/unixMain/kotlin/okio/UnixPosixVariant.kt | 12 ++++-------- .../kotlin/okio/internal/PosixDirectory.kt | 3 +-- .../kotlin/okio/internal/PosixDirectory.kt | 15 +++++++-------- 5 files changed, 20 insertions(+), 28 deletions(-) rename okio/src/{nativeMain => unixMain}/kotlin/okio/internal/PosixDirectory.kt (89%) rename okio/src/{nativeNonAndroidMain => unixNonAndroidMain}/kotlin/okio/internal/PosixDirectory.kt (67%) diff --git a/okio/build.gradle.kts b/okio/build.gradle.kts index f21e5c0e4b..d29d4bf18d 100644 --- a/okio/build.gradle.kts +++ b/okio/build.gradle.kts @@ -189,9 +189,8 @@ kotlin { children = appleTargets - "macosX64", ) } + createSourceSet("unixNonAndroidMain", parent = unixMain, children = appleTargets + linuxTargets) } - - createSourceSet("nativeNonAndroidMain", parent = nativeMain, children = appleTargets + mingwTargets + linuxTargets) } createSourceSet("nativeTest", parent = commonTest, children = androidNativeTargets + mingwTargets + linuxTargets) diff --git a/okio/src/androidNativeMain/kotlin/okio/internal/PosixDirectory.kt b/okio/src/androidNativeMain/kotlin/okio/internal/PosixDirectory.kt index 6da1e6f318..2f6e2ff1b4 100644 --- a/okio/src/androidNativeMain/kotlin/okio/internal/PosixDirectory.kt +++ b/okio/src/androidNativeMain/kotlin/okio/internal/PosixDirectory.kt @@ -15,22 +15,21 @@ */ package okio.internal -import kotlinx.cinterop.COpaquePointer +import cnames.structs.DIR +import kotlinx.cinterop.CPointer 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() { +private class AndroidPosixDirectory(private val dir: CPointer) : PosixDirectory { + override fun nextEntry() = readdir(dir.reinterpret()) + 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) +internal actual fun openPosixDirectory(path: Path): PosixDirectory? { + return opendir(path.toString())?.let(::AndroidPosixDirectory) } diff --git a/okio/src/unixMain/kotlin/okio/UnixPosixVariant.kt b/okio/src/unixMain/kotlin/okio/UnixPosixVariant.kt index ee3442b8c6..eaee991895 100644 --- a/okio/src/unixMain/kotlin/okio/UnixPosixVariant.kt +++ b/okio/src/unixMain/kotlin/okio/UnixPosixVariant.kt @@ -25,6 +25,7 @@ import kotlinx.cinterop.get import kotlinx.cinterop.memScoped import kotlinx.cinterop.toKString import okio.Path.Companion.toPath +import okio.internal.openPosixDirectory import okio.internal.toPath import platform.posix.ENOENT import platform.posix.FILE @@ -34,7 +35,6 @@ import platform.posix.O_RDWR import platform.posix.PATH_MAX import platform.posix.S_IFLNK import platform.posix.S_IFMT -import platform.posix.closedir import platform.posix.dirent import platform.posix.errno import platform.posix.fdopen @@ -44,10 +44,8 @@ import platform.posix.free import platform.posix.getenv import platform.posix.mkdir import platform.posix.open -import platform.posix.opendir import platform.posix.pread import platform.posix.pwrite -import platform.posix.readdir import platform.posix.readlink import platform.posix.realpath import platform.posix.remove @@ -81,16 +79,16 @@ internal actual fun PosixFileSystem.variantDelete(path: Path, mustExist: Boolean } internal actual fun PosixFileSystem.variantList(dir: Path, throwOnFailure: Boolean): List? { - val opendir = opendir(dir.toString()) + val opendir = openPosixDirectory(dir) ?: if (throwOnFailure) throw errnoToIOException(errno) else return null - try { + opendir.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: CPointer = opendir.nextEntry() ?: break val childPath = buffer.writeNullTerminated( bytes = dirent[0].d_name, ).toPath(normalize = true) @@ -112,8 +110,6 @@ internal actual fun PosixFileSystem.variantList(dir: Path, throwOnFailure: Boole result.sort() return result - } finally { - closedir(opendir) // Ignore errno from closedir. } } diff --git a/okio/src/nativeMain/kotlin/okio/internal/PosixDirectory.kt b/okio/src/unixMain/kotlin/okio/internal/PosixDirectory.kt similarity index 89% rename from okio/src/nativeMain/kotlin/okio/internal/PosixDirectory.kt rename to okio/src/unixMain/kotlin/okio/internal/PosixDirectory.kt index 31ad141cd2..967bece558 100644 --- a/okio/src/nativeMain/kotlin/okio/internal/PosixDirectory.kt +++ b/okio/src/unixMain/kotlin/okio/internal/PosixDirectory.kt @@ -15,7 +15,6 @@ */ package okio.internal -import kotlinx.cinterop.COpaquePointer import kotlinx.cinterop.CPointer import okio.Closeable import okio.Path @@ -29,7 +28,7 @@ import platform.posix.dirent * [PosixDirectory] provides platform-specific implementation * for `DIR`-related functionality. */ -internal expect value class PosixDirectory(private val dir: COpaquePointer) : Closeable { +internal interface PosixDirectory : Closeable { fun nextEntry(): CPointer? override fun close() } diff --git a/okio/src/nativeNonAndroidMain/kotlin/okio/internal/PosixDirectory.kt b/okio/src/unixNonAndroidMain/kotlin/okio/internal/PosixDirectory.kt similarity index 67% rename from okio/src/nativeNonAndroidMain/kotlin/okio/internal/PosixDirectory.kt rename to okio/src/unixNonAndroidMain/kotlin/okio/internal/PosixDirectory.kt index 6da1e6f318..dc1f1f49f5 100644 --- a/okio/src/nativeNonAndroidMain/kotlin/okio/internal/PosixDirectory.kt +++ b/okio/src/unixNonAndroidMain/kotlin/okio/internal/PosixDirectory.kt @@ -15,22 +15,21 @@ */ package okio.internal -import kotlinx.cinterop.COpaquePointer +import kotlinx.cinterop.CPointer import kotlinx.cinterop.reinterpret -import okio.Closeable import okio.Path +import platform.posix.DIR 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() { +private class UnixPosixDirectory(private val dir: CPointer) : PosixDirectory { + override fun nextEntry() = readdir(dir.reinterpret()) + 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) +internal actual fun openPosixDirectory(path: Path): PosixDirectory? { + return opendir(path.toString())?.let(::UnixPosixDirectory) } From 8d01adffd79160a26ae3afbcf04aa900bd2d6416 Mon Sep 17 00:00:00 2001 From: MohammedKHC Date: Fri, 7 Aug 2026 15:17:00 +0300 Subject: [PATCH 10/16] Fix statx on Android native. --- okio/build.gradle.kts | 1 + .../kotlin/okio/AndroidPosixVariant.kt | 11 +++ .../kotlin/okio/LinuxPosixVariant.kt | 81 ++++++++++--------- .../kotlin/okio/LinuxPosixVariant.kt | 6 ++ 4 files changed, 63 insertions(+), 36 deletions(-) create mode 100644 okio/src/androidNativeMain/kotlin/okio/AndroidPosixVariant.kt create mode 100644 okio/src/linuxNonAndroidMain/kotlin/okio/LinuxPosixVariant.kt diff --git a/okio/build.gradle.kts b/okio/build.gradle.kts index d29d4bf18d..158a212a25 100644 --- a/okio/build.gradle.kts +++ b/okio/build.gradle.kts @@ -176,6 +176,7 @@ kotlin { children = linuxTargets, ).also { linuxMain -> linuxMain.dependsOn(nonAppleMain) + createSourceSet("linuxNonAndroidMain", parent = linuxMain, children = linuxTargets) createSourceSet("androidNativeMain", parent = linuxMain, children = androidNativeTargets) } createSourceSet( diff --git a/okio/src/androidNativeMain/kotlin/okio/AndroidPosixVariant.kt b/okio/src/androidNativeMain/kotlin/okio/AndroidPosixVariant.kt new file mode 100644 index 0000000000..7b5c21cd70 --- /dev/null +++ b/okio/src/androidNativeMain/kotlin/okio/AndroidPosixVariant.kt @@ -0,0 +1,11 @@ +package okio + +import kotlin.concurrent.Volatile +import platform.posix.android_get_device_api_level + +/** + * Checked eagerly because on older Android versions (API < 30) + * seccomp blocks the syscall with SIGSYS, crashing the app instead of returning ENOSYS. + **/ +@Volatile +internal actual var isStatXSupported = android_get_device_api_level() >= 30 diff --git a/okio/src/linuxMain/kotlin/okio/LinuxPosixVariant.kt b/okio/src/linuxMain/kotlin/okio/LinuxPosixVariant.kt index bd54512cba..25205816f2 100644 --- a/okio/src/linuxMain/kotlin/okio/LinuxPosixVariant.kt +++ b/okio/src/linuxMain/kotlin/okio/LinuxPosixVariant.kt @@ -37,6 +37,8 @@ import platform.posix.lstat import platform.posix.stat import platform.posix.syscall +internal expect var isStatXSupported: Boolean + /** * Prefer `statx()` if it's available. Fall back to `stat()` which doesn't have a field for * `createdAt`. @@ -44,45 +46,52 @@ import platform.posix.syscall @OptIn(UnsafeNumber::class) internal actual fun PosixFileSystem.variantMetadataOrNull(path: Path): FileMetadata? { memScoped { - val statx = alloc() - val result = syscall( - __NR_statx.convert(), - AT_FDCWD, - path.toString(), - AT_SYMLINK_NOFOLLOW, - STATX_BASIC_STATS or STATX_BTIME, - statx.ptr, - ).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, - symlinkTarget = symlinkTarget(statx.stx_mode.toInt(), path), - size = statx.stx_size.toLong(), - createdAtMillis = when { - statx.stx_mask and STATX_BTIME != 0U -> statx.stx_btime.epochMillis - else -> statx.stx_mtime.epochMillis - }, - lastModifiedAtMillis = statx.stx_mtime.epochMillis, - lastAccessedAtMillis = statx.stx_atime.epochMillis, - ) - } - - // Recover if statx() isn't available. It first appeared in Linux in 4.11 (2017-04-30) and - // Android in API 30 (2020-09-08). - if (errno == ENOSYS) { - val stat = alloc() - if (lstat(path.toString(), stat.ptr) == 0) { + if (isStatXSupported) { + val statx = alloc() + val result = syscall( + __NR_statx.convert(), + AT_FDCWD, + path.toString(), + AT_SYMLINK_NOFOLLOW, + STATX_BASIC_STATS or STATX_BTIME, + statx.ptr, + ).convert() + if (result == 0) { return FileMetadata( - isRegularFile = stat.st_mode.toInt() and S_IFMT == S_IFREG, - isDirectory = stat.st_mode.toInt() and S_IFMT == S_IFDIR, - symlinkTarget = symlinkTarget(stat.st_mode.toInt(), path), - size = stat.st_size, - createdAtMillis = stat.st_mtim.epochMillis, - lastModifiedAtMillis = stat.st_mtim.epochMillis, - lastAccessedAtMillis = stat.st_atim.epochMillis, + isRegularFile = statx.stx_mode.toInt() and S_IFMT == S_IFREG, + isDirectory = statx.stx_mode.toInt() and S_IFMT == S_IFDIR, + symlinkTarget = symlinkTarget(statx.stx_mode.toInt(), path), + size = statx.stx_size.toLong(), + createdAtMillis = when { + statx.stx_mask and STATX_BTIME != 0U -> statx.stx_btime.epochMillis + else -> statx.stx_mtime.epochMillis + }, + lastModifiedAtMillis = statx.stx_mtime.epochMillis, + lastAccessedAtMillis = statx.stx_atime.epochMillis, ) } + + // Recover if statx() isn't available. It first appeared in Linux in 4.11 (2017-04-30) and + // Android in API 30 (2020-09-08). + if (errno == ENOSYS) { + isStatXSupported = false + } else { + if (errno == ENOENT) return null + throw errnoToIOException(errno) + } + } + + val stat = alloc() + if (lstat(path.toString(), stat.ptr) == 0) { + return FileMetadata( + isRegularFile = stat.st_mode.toInt() and S_IFMT == S_IFREG, + isDirectory = stat.st_mode.toInt() and S_IFMT == S_IFDIR, + symlinkTarget = symlinkTarget(stat.st_mode.toInt(), path), + size = stat.st_size, + createdAtMillis = stat.st_mtim.epochMillis, + lastModifiedAtMillis = stat.st_mtim.epochMillis, + lastAccessedAtMillis = stat.st_atim.epochMillis, + ) } if (errno == ENOENT) return null diff --git a/okio/src/linuxNonAndroidMain/kotlin/okio/LinuxPosixVariant.kt b/okio/src/linuxNonAndroidMain/kotlin/okio/LinuxPosixVariant.kt new file mode 100644 index 0000000000..65184733ed --- /dev/null +++ b/okio/src/linuxNonAndroidMain/kotlin/okio/LinuxPosixVariant.kt @@ -0,0 +1,6 @@ +package okio + +import kotlin.concurrent.Volatile + +@Volatile +internal actual var isStatXSupported = true From 80f8a844da4b1b148b46a7b942b5aed7c937d8ea Mon Sep 17 00:00:00 2001 From: MohammedKHC Date: Fri, 7 Aug 2026 15:27:05 +0300 Subject: [PATCH 11/16] Cleanup --- okio/src/nativeMain/kotlin/okio/PosixFileSystem.kt | 3 --- 1 file changed, 3 deletions(-) diff --git a/okio/src/nativeMain/kotlin/okio/PosixFileSystem.kt b/okio/src/nativeMain/kotlin/okio/PosixFileSystem.kt index e81043e67c..3178e6fa03 100644 --- a/okio/src/nativeMain/kotlin/okio/PosixFileSystem.kt +++ b/okio/src/nativeMain/kotlin/okio/PosixFileSystem.kt @@ -15,10 +15,7 @@ */ package okio -import kotlinx.cinterop.get import okio.Path.Companion.toPath -import okio.internal.openPosixDirectory -import okio.internal.toPath import platform.posix.EEXIST import platform.posix.errno From 2efb6a9283e521985869e1bb282dd239c7c8698a Mon Sep 17 00:00:00 2001 From: MohammedKHC Date: Fri, 7 Aug 2026 15:45:44 +0300 Subject: [PATCH 12/16] apiDump --- okio/api/okio.klib.api | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/okio/api/okio.klib.api b/okio/api/okio.klib.api index 5effa9a883..facb5b2ff4 100644 --- a/okio/api/okio.klib.api +++ b/okio/api/okio.klib.api @@ -1,6 +1,6 @@ // Klib ABI Dump -// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, linuxArm64, linuxX64, macosArm64, macosX64, mingwX64, tvosArm64, tvosSimulatorArm64, tvosX64, wasmJs, wasmWasi, watchosArm32, watchosArm64, watchosDeviceArm64, watchosSimulatorArm64, watchosX64] -// Alias: native => [iosArm64, iosSimulatorArm64, iosX64, linuxArm64, linuxX64, macosArm64, macosX64, mingwX64, tvosArm64, tvosSimulatorArm64, tvosX64, watchosArm32, watchosArm64, watchosDeviceArm64, watchosSimulatorArm64, watchosX64] +// Targets: [androidNativeArm32, androidNativeArm64, androidNativeX64, androidNativeX86, iosArm64, iosSimulatorArm64, iosX64, js, linuxArm64, linuxX64, macosArm64, macosX64, mingwX64, tvosArm64, tvosSimulatorArm64, tvosX64, wasmJs, wasmWasi, watchosArm32, watchosArm64, watchosDeviceArm64, watchosSimulatorArm64, watchosX64] +// Alias: native => [androidNativeArm32, androidNativeArm64, androidNativeX64, androidNativeX86, iosArm64, iosSimulatorArm64, iosX64, linuxArm64, linuxX64, macosArm64, macosX64, mingwX64, tvosArm64, tvosSimulatorArm64, tvosX64, watchosArm32, watchosArm64, watchosDeviceArm64, watchosSimulatorArm64, watchosX64] // Alias: apple => [iosArm64, iosSimulatorArm64, iosX64, macosArm64, macosX64, tvosArm64, tvosSimulatorArm64, tvosX64, watchosArm32, watchosArm64, watchosDeviceArm64, watchosSimulatorArm64, watchosX64] // Rendering settings: // - Signature version: 2 From 22c3b14b620ea3d66b6f6f36ddd4ced1014d5e44 Mon Sep 17 00:00:00 2001 From: MohammedKHC Date: Fri, 7 Aug 2026 15:46:31 +0300 Subject: [PATCH 13/16] Test android native on CI --- .github/workflows/build.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ba836b7bae..3185f9a324 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -59,10 +59,18 @@ jobs: - uses: gradle/actions/setup-gradle@v6 + - name: Build Android native test binary + run: ./gradlew :okio:androidNativeX64TestBinaries + - uses: reactivecircus/android-emulator-runner@v2 with: api-level: 24 - script: ./gradlew :okio-assetfilesystem:connectedCheck + arch: x86_64 + script: | + adb push okio/build/bin/androidNativeX64/debugTest/test.kexe /data/local/tmp + adb push okio-testing-support /data/local/tmp/okio/okio-testing-support + adb shell "OKIO_ROOT=/data/local/tmp/okio /data/local/tmp/test.kexe" + ./gradlew :okio-assetfilesystem:connectedCheck loom: runs-on: ubuntu-latest From 2341f891fe73b35e4c26b48f3ebd3181a581c3d9 Mon Sep 17 00:00:00 2001 From: MohammedKHC Date: Fri, 7 Aug 2026 16:04:40 +0300 Subject: [PATCH 14/16] Set `fileSystemHasGoodMetadata` to false on Android. And ignore the following tests 1. `listOnRelativePathWhichIsNotDotReturnsRelativePaths` 2. `listOrNullOnRelativePathWhichIsNotDotReturnsRelativePaths` as we don't really want to change the working directroy of the running test executable. --- .../src/commonMain/kotlin/okio/AbstractFileSystemTest.kt | 4 ++++ .../src/commonMain/kotlin/okio/TestingCommon.kt | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/okio-testing-support/src/commonMain/kotlin/okio/AbstractFileSystemTest.kt b/okio-testing-support/src/commonMain/kotlin/okio/AbstractFileSystemTest.kt index f669b3eb2a..42d14cb651 100644 --- a/okio-testing-support/src/commonMain/kotlin/okio/AbstractFileSystemTest.kt +++ b/okio-testing-support/src/commonMain/kotlin/okio/AbstractFileSystemTest.kt @@ -52,6 +52,8 @@ abstract class AbstractFileSystemTest( private val isNodeJsFileSystem = fileSystem::class.simpleName?.startsWith("NodeJs") ?: false private val isWasiFileSystem = fileSystem::class.simpleName?.startsWith("Wasi") ?: false private val isWrappingJimFileSystem = this::class.simpleName?.contains("JimFileSystem") ?: false + private val isAndroidNativeFileSystem = getEnv("ANDROID_DATA") != null && + fileSystem::class.simpleName?.startsWith("Posix") ?: false @Test fun doesNotExistsWithInvalidPathDoesNotThrow() { @@ -283,6 +285,7 @@ abstract class AbstractFileSystemTest( @Test fun listOnRelativePathWhichIsNotDotReturnsRelativePaths() { if (isNodeJsFileSystem) return + if (isAndroidNativeFileSystem) return val apiDir = "api".toPath() val expectedFiles = listOf( @@ -336,6 +339,7 @@ abstract class AbstractFileSystemTest( @Test fun listOrNullOnRelativePathWhichIsNotDotReturnsRelativePaths() { if (isNodeJsFileSystem) return + if (isAndroidNativeFileSystem) return val apiDir = "api".toPath() val expectedFiles = listOf( diff --git a/okio-testing-support/src/commonMain/kotlin/okio/TestingCommon.kt b/okio-testing-support/src/commonMain/kotlin/okio/TestingCommon.kt index 24cf7b82c7..1f8a90e029 100644 --- a/okio-testing-support/src/commonMain/kotlin/okio/TestingCommon.kt +++ b/okio-testing-support/src/commonMain/kotlin/okio/TestingCommon.kt @@ -46,7 +46,7 @@ expect fun isBrowser(): Boolean * The file system that GitHub actions gives us doesn't do anything when we `touch` a file. */ val fileSystemHasGoodMetadata: Boolean - get() = getEnv("GITHUB_WORKSPACE") == null + get() = getEnv("GITHUB_WORKSPACE") == null && getEnv("ANDROID_DATA") == null val FileMetadata.createdAt: Instant? get() { From 5619010245f60aabd4e711b83bec9f568f8f5f5c Mon Sep 17 00:00:00 2001 From: MohammedKHC Date: Fri, 7 Aug 2026 16:15:17 +0300 Subject: [PATCH 15/16] apiDumb fakefilesystem. --- okio-fakefilesystem/api/okio-fakefilesystem.klib.api | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/okio-fakefilesystem/api/okio-fakefilesystem.klib.api b/okio-fakefilesystem/api/okio-fakefilesystem.klib.api index 2e42041f7d..475ac2db79 100644 --- a/okio-fakefilesystem/api/okio-fakefilesystem.klib.api +++ b/okio-fakefilesystem/api/okio-fakefilesystem.klib.api @@ -1,5 +1,5 @@ // Klib ABI Dump -// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, linuxArm64, linuxX64, macosArm64, macosX64, mingwX64, tvosArm64, tvosSimulatorArm64, tvosX64, wasmJs, watchosArm32, watchosArm64, watchosDeviceArm64, watchosSimulatorArm64, watchosX64] +// Targets: [androidNativeArm32, androidNativeArm64, androidNativeX64, androidNativeX86, iosArm64, iosSimulatorArm64, iosX64, js, linuxArm64, linuxX64, macosArm64, macosX64, mingwX64, tvosArm64, tvosSimulatorArm64, tvosX64, wasmJs, watchosArm32, watchosArm64, watchosDeviceArm64, watchosSimulatorArm64, watchosX64] // Rendering settings: // - Signature version: 2 // - Show manifest properties: true From 12d49c5d8c422b375d3ca78d3caadd793d23415c Mon Sep 17 00:00:00 2001 From: Mohammed Khaled Date: Fri, 7 Aug 2026 16:33:56 +0300 Subject: [PATCH 16/16] Fix browser tests. --- .../src/commonMain/kotlin/okio/AbstractFileSystemTest.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/okio-testing-support/src/commonMain/kotlin/okio/AbstractFileSystemTest.kt b/okio-testing-support/src/commonMain/kotlin/okio/AbstractFileSystemTest.kt index 42d14cb651..9f51de81a6 100644 --- a/okio-testing-support/src/commonMain/kotlin/okio/AbstractFileSystemTest.kt +++ b/okio-testing-support/src/commonMain/kotlin/okio/AbstractFileSystemTest.kt @@ -52,8 +52,8 @@ abstract class AbstractFileSystemTest( private val isNodeJsFileSystem = fileSystem::class.simpleName?.startsWith("NodeJs") ?: false private val isWasiFileSystem = fileSystem::class.simpleName?.startsWith("Wasi") ?: false private val isWrappingJimFileSystem = this::class.simpleName?.contains("JimFileSystem") ?: false - private val isAndroidNativeFileSystem = getEnv("ANDROID_DATA") != null && - fileSystem::class.simpleName?.startsWith("Posix") ?: false + private val isAndroidNativeFileSystem = fileSystem::class.simpleName?.startsWith("Posix") ?: false && + getEnv("ANDROID_DATA") != null @Test fun doesNotExistsWithInvalidPathDoesNotThrow() {