IJPL-217737 IJent: Posix-to-DOS FileAttributeView adapter

GitOrigin-RevId: de5c63d4a310ba3ef225f3dfba70e7758f5d2b71
This commit is contained in:
Vladimir Lagunov
2025-11-10 18:58:00 +00:00
committed by intellij-monorepo-bot
parent 47cea42589
commit 104946b962
2 changed files with 84 additions and 5 deletions
@@ -2,6 +2,7 @@
package com.intellij.platform.ide.impl.wsl.ijent.nio
import com.intellij.execution.ijent.nio.getCachedFileAttributesAndWrapToDosAttributesAdapter
import com.intellij.execution.ijent.nio.getFileAttributeViewUsingDosAttributesAdapter
import com.intellij.execution.ijent.nio.readAttributesUsingDosAttributesAdapter
import com.intellij.execution.wsl.WslDistributionManager
import com.intellij.execution.wsl.WslPath
@@ -302,8 +303,8 @@ class IjentWslNioFileSystemProvider(
override fun getFileStore(path: Path): FileStore =
ijentFsProvider.getFileStore(path.toIjentPath())
override fun <V : FileAttributeView?> getFileAttributeView(path: Path, type: Class<V>, vararg options: LinkOption): V =
ijentFsProvider.getFileAttributeView(path.toIjentPath(), type, *options)
override fun <V : FileAttributeView> getFileAttributeView(path: Path, type: Class<V>, vararg options: LinkOption): V =
ijentFsProvider.getFileAttributeViewUsingDosAttributesAdapter(path.toIjentPath(), type, *options)
override fun <A : BasicFileAttributes> readAttributes(path: Path, type: Class<A>, vararg options: LinkOption): A {
return ijentFsProvider.readAttributesUsingDosAttributesAdapter(path, path.toIjentPath(), type, *options)
@@ -12,9 +12,7 @@ import com.intellij.platform.ijent.community.impl.nio.IjentNioPosixFileAttribute
import org.jetbrains.annotations.ApiStatus
import java.nio.file.LinkOption
import java.nio.file.Path
import java.nio.file.attribute.BasicFileAttributes
import java.nio.file.attribute.DosFileAttributes
import java.nio.file.attribute.PosixFileAttributes
import java.nio.file.attribute.*
import java.nio.file.attribute.PosixFilePermission.*
import java.nio.file.spi.FileSystemProvider
import kotlin.io.path.name
@@ -111,4 +109,84 @@ class IjentNioPosixFileAttributesWithDosAdapter(
override fun getCaseSensitivity(): FileAttributes.CaseSensitivity {
if (fileInfo is CaseSensitivityAttribute) return fileInfo.caseSensitivity else return FileAttributes.CaseSensitivity.UNKNOWN
}
}
@ApiStatus.Internal
class IjentNioPosixFileAttributeViewWithDosAdapter(
private val userInfo: EelUserPosixInfo,
private val posixView: PosixFileAttributeView,
private val nameStartsWithDot: Boolean,
) : PosixFileAttributeView by posixView, DosFileAttributeView {
override fun readAttributes(): IjentNioPosixFileAttributesWithDosAdapter =
IjentNioPosixFileAttributesWithDosAdapter(userInfo, posixView.readAttributes(), nameStartsWithDot)
override fun setReadOnly(readOnly: Boolean) {
val permissions: MutableSet<PosixFilePermission> = posixView.readAttributes().permissions()
// "Read-only" implies "readable", "not read-only" implies "not only readable". In any case, the resource is supposed to be readable.
permissions += OWNER_READ
if (readOnly) {
permissions -= OWNER_WRITE
permissions -= GROUP_WRITE
permissions -= OTHERS_WRITE
}
else {
// Windows has a complicated ACL for every file, but this option refers to the old DOS attribute.
// MS DOS was not a multi-user operating system, but Posix systems are.
// The dilemma is in how to treat the request to setting the read-only attribute as false:
// make the file readable for everyone or only for the owner.
// This code explicitly sets only for the user because in the worst but rare scenario it leads to non-functioning features,
// but too broad permissions can hypothetically lead to a security issue.
permissions += OWNER_WRITE
}
posixView.setPermissions(permissions)
}
override fun setHidden(value: Boolean) {
// There's no such conception as a hidden file in terms of the Posix filesystem,
// but there's a tradition to treat all files starting from `.` as hidden.
//
// File renaming is certainly something that the caller of `DosFileAttribute.setHidden` does not expect.
// Throwing an error might have been possible if this implementation was introduced for new code,
// but it is here to support unknown legacy code.
//
// Lastly, it might be worth using extended attributes like `sun.nio.fs.LinuxDosFileAttributeView` does,
// but it's usually unexpected, it's not supported on macOS, and also it requires efforts for implementing.
// Reference: https://github.com/JetBrains/JetBrainsRuntime/blob/922b12f30c4cfd6b504d66daf37fb30c7fb1bfe7/src/java.base/linux/classes/sun/nio/fs/LinuxDosFileAttributeView.java
//
// Thus, it's better to do nothing in this method.
}
override fun setSystem(value: Boolean) {
// There's no such conception as a "system file" in Posix, though it might be implemented like in `sun.nio.fs.LinuxDosFileAttributeView`
}
override fun setArchive(value: Boolean) {
// There's no such conception as a "system file" in Posix, though it might be implemented like in `sun.nio.fs.LinuxDosFileAttributeView`
}
}
@ApiStatus.Internal
fun <V : FileAttributeView> FileSystemProvider.getFileAttributeViewUsingDosAttributesAdapter(
ijentPath: IjentNioPath,
type: Class<V>,
vararg options: LinkOption,
): V {
val actualType = when {
DosFileAttributeView::class.java.isAssignableFrom(type) -> PosixFileAttributeView::class.java
else -> type
}
val resultAttrs = when (val actualView = getFileAttributeView(ijentPath, actualType, *options)) {
is PosixFileAttributeView -> IjentNioPosixFileAttributeViewWithDosAdapter(
userInfo = ijentPath.fileSystem.ijentFs.user as EelUserPosixInfo,
posixView = actualView,
nameStartsWithDot = ijentPath.name.startsWith("."),
)
else -> actualView
}
return type.cast(resultAttrs)
}