wireguard-android/ui/src/main/java/com/wireguard/android/configStore/FileConfigStore.kt

83 lines
3.1 KiB
Kotlin

/*
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
package com.wireguard.android.configStore
import android.content.Context
import android.util.Log
import com.wireguard.android.R
import com.wireguard.config.BadConfigException
import com.wireguard.config.Config
import java.io.File
import java.io.FileInputStream
import java.io.FileNotFoundException
import java.io.FileOutputStream
import java.io.IOException
import java.nio.charset.StandardCharsets
/**
* Configuration store that uses a `wg-quick`-style file for each configured tunnel.
*/
class FileConfigStore(private val context: Context) : ConfigStore {
@Throws(IOException::class)
override fun create(name: String, config: Config): Config {
Log.d(TAG, "Creating configuration for tunnel $name")
val file = fileFor(name)
if (!file.createNewFile())
throw IOException(context.getString(R.string.config_file_exists_error, file.name))
FileOutputStream(file, false).use { it.write(config.toWgQuickString().toByteArray(StandardCharsets.UTF_8)) }
return config
}
@Throws(IOException::class)
override fun delete(name: String) {
Log.d(TAG, "Deleting configuration for tunnel $name")
val file = fileFor(name)
if (!file.delete())
throw IOException(context.getString(R.string.config_delete_error, file.name))
}
override fun enumerate(): Set<String> {
return context.fileList()
.filter { it.endsWith(".conf") }
.map { it.substring(0, it.length - ".conf".length) }
.toSet()
}
private fun fileFor(name: String): File {
return File(context.filesDir, "$name.conf")
}
@Throws(BadConfigException::class, IOException::class)
override fun load(name: String): Config {
FileInputStream(fileFor(name)).use { stream -> return Config.parse(stream) }
}
@Throws(IOException::class)
override fun rename(name: String, replacement: String) {
Log.d(TAG, "Renaming configuration for tunnel $name to $replacement")
val file = fileFor(name)
val replacementFile = fileFor(replacement)
if (!replacementFile.createNewFile()) throw IOException(context.getString(R.string.config_exists_error, replacement))
if (!file.renameTo(replacementFile)) {
if (!replacementFile.delete()) Log.w(TAG, "Couldn't delete marker file for new name $replacement")
throw IOException(context.getString(R.string.config_rename_error, file.name))
}
}
@Throws(IOException::class)
override fun save(name: String, config: Config): Config {
Log.d(TAG, "Saving configuration for tunnel $name")
val file = fileFor(name)
if (!file.isFile)
throw FileNotFoundException(context.getString(R.string.config_not_found_error, file.name))
FileOutputStream(file, false).use { stream -> stream.write(config.toWgQuickString().toByteArray(StandardCharsets.UTF_8)) }
return config
}
companion object {
private const val TAG = "WireGuard/FileConfigStore"
}
}