Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document the file system #1056

Merged
merged 1 commit into from
Oct 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 125 additions & 0 deletions docs/file_system.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
File System
===========

Okio's file system is designed to be easy, testable, multiplatform, and efficient.

### Easy

Reading and writing files is concise yet flexible.

```kotlin
val path = "README.md".toPath()

val readmeContent = FileSystem.SYSTEM.read(path) {
readUtf8()
}

val updatedContent = readmeContent.replace("red", "blue")

FileSystem.SYSTEM.write(path) {
writeUtf8(updatedContent)
}
```


### Testable

It's easy to swap out the real file system with a fake. This makes tests run faster and more
reliably.

```kotlin
val fileSystem = FakeFileSystem()
val userHome = "/Users/sandy".toPath()
val gitConfig = userHome / ".gitconfig"

fileSystem.createDirectories(userHome)
val original = """
|[user]
| email = [email protected]
|""".trimMargin()
fileSystem.write(gitConfig) { writeUtf8(original) }

GitConfigFixer(fileSystem).fix(userHome)

val expected = """
|[user]
| email = [email protected]
|[diff]
| renames = true
| indentHeuristic = on
""".trimIndent()
assertEquals(expected, fileSystem.read(gitConfig) { readUtf8() })
```

With `ForwardingFileSystem` you can easily inject faults to confirm your program is graceful even
when the user's disk fills up.


### Multiplatform

Okio’s `Path` class supports Windows-style (like `C:\autoexec.bat`) and UNIX-style paths
(like `/etc/passwd`). It supports manipulating Windows paths on UNIX, and UNIX paths on Windows.

The system `FileSystem` abstracts over these platform APIs:

* Android API levels <26: [java.io.File](https://developer.android.com/reference/java/io/File)
* Java and Android API level 26+: [java.nio.file](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/nio/file/FileSystem.html)
* Linux: [man pages](https://www.kernel.org/doc/man-pages/)
* UNIX: [stdio.h](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/stdio.h.html)
* Windows: [fileapi.h](https://docs.microsoft.com/en-us/windows/win32/api/fileapi/)
* Node.js: [file system](https://nodejs.org/api/fs.html)


### Efficient

Read and write operations integrate with Okio buffers to reduce the number of system calls.

It exposes high-level operations like `atomicMove()` and `metadata` to get the OS to do all the work
when appropriate.


## Known Issues


Okio's implementation is constrained by the capabilities its underlying APIs. This page is an
overview of these limitations.


### All Platforms

* There are no APIs for file permissions, watches, volume management, memory mapping, or locking.
* Paths that cannot be represented as UTF-8 strings are unsupported. The underlying APIs that Okio
calls through, including `java.io.File`, all treat paths as strings.


### Kotlin/JVM

#### On Android, API level less than 26:

* Creating and accessing symlinks is unsupported.


#### On Windows:

* `FileSystem.atomicMove()` fails if the target file already exists.


### Kotlin/Native

* FakeFileSystem does not support concurrent use. We are [holding off on this][fake_fs_concurrency]
until the upcoming memory model is released.

#### On Windows:

* Creating and accessing symlinks is unsupported.


### Kotlin/JS

* NodeJsFileSystem's `source()` and `sink()` cannot access UNIX pipes.
* Instead of returning null, `NodeJsFileSystem.metadataOrNull()` throws `IOException` if the path
is invalid. (In the Node.js API there's no mechanism to differentiate between a failure to read
a valid path and a rejection of an invalid path.)


[fake_fs_concurrency]: https://github.com/square/okio/issues/950
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ nav:
- '2.x API': 2.x/okio/okio/index.html
- '1.x API ⏏': https://square.github.io/okio/1.x/okio/
- 'Change Log': changelog.md
- 'File System': file_system.md
- 'Multiplatform': multiplatform.md
- 'Contributing': contributing.md
- 'Code of Conduct': code_of_conduct.md
Expand Down