xref: /aosp_15_r20/external/okio/okio/src/jvmMain/kotlin/okio/NioSystemFileSystem.kt (revision f9742813c14b702d71392179818a9e591da8620c)
1 /*
2  * Copyright (C) 2020 Square, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package okio
17 
18 import java.nio.file.FileSystemException
19 import java.nio.file.Files
20 import java.nio.file.LinkOption
21 import java.nio.file.NoSuchFileException
22 import java.nio.file.Path as NioPath
23 import java.nio.file.StandardCopyOption.ATOMIC_MOVE
24 import java.nio.file.StandardCopyOption.REPLACE_EXISTING
25 import java.nio.file.attribute.BasicFileAttributes
26 import java.nio.file.attribute.FileTime
27 import okio.Path.Companion.toOkioPath
28 
29 /**
30  * Extends [JvmSystemFileSystem] for platforms that support `java.nio.file` first introduced in
31  * Java 7 and Android 8.0 (API level 26).
32  */
33 internal open class NioSystemFileSystem : JvmSystemFileSystem() {
metadataOrNullnull34   override fun metadataOrNull(path: Path): FileMetadata? {
35     return metadataOrNull(path.toNioPath())
36   }
37 
metadataOrNullnull38   protected fun metadataOrNull(nioPath: NioPath): FileMetadata? {
39     val attributes = try {
40       Files.readAttributes(
41         nioPath,
42         BasicFileAttributes::class.java,
43         LinkOption.NOFOLLOW_LINKS,
44       )
45     } catch (_: NoSuchFileException) {
46       return null
47     } catch (_: FileSystemException) {
48       return null
49     }
50 
51     val symlinkTarget: NioPath? = if (attributes.isSymbolicLink) {
52       Files.readSymbolicLink(nioPath)
53     } else {
54       null
55     }
56 
57     return FileMetadata(
58       isRegularFile = attributes.isRegularFile,
59       isDirectory = attributes.isDirectory,
60       symlinkTarget = symlinkTarget?.toOkioPath(),
61       size = attributes.size(),
62       createdAtMillis = attributes.creationTime()?.zeroToNull(),
63       lastModifiedAtMillis = attributes.lastModifiedTime()?.zeroToNull(),
64       lastAccessedAtMillis = attributes.lastAccessTime()?.zeroToNull(),
65     )
66   }
67 
68   /**
69    * Returns this time as an epoch millis. If this is 0L this returns null, because epoch time 0L is
70    * a special value that indicates the requested time was not available.
71    */
FileTimenull72   private fun FileTime.zeroToNull(): Long? {
73     return toMillis().takeIf { it != 0L }
74   }
75 
atomicMovenull76   override fun atomicMove(source: Path, target: Path) {
77     try {
78       Files.move(source.toNioPath(), target.toNioPath(), ATOMIC_MOVE, REPLACE_EXISTING)
79     } catch (e: NoSuchFileException) {
80       throw FileNotFoundException(e.message)
81     } catch (e: UnsupportedOperationException) {
82       throw IOException("atomic move not supported")
83     }
84   }
85 
createSymlinknull86   override fun createSymlink(source: Path, target: Path) {
87     Files.createSymbolicLink(source.toNioPath(), target.toNioPath())
88   }
89 
toStringnull90   override fun toString() = "NioSystemFileSystem"
91 }
92