forked from hardcoresushi/DroidFS
Direct encrypted files read/write & More compliant EncryptedVolumeDataSource
This commit is contained in:
parent
8f5afca823
commit
7cdfc32c31
@ -1 +1 @@
|
||||
Subproject commit c0600c262480f6fb3d31e2b500ba04714f1ff342
|
||||
Subproject commit dc82772e5eb8063bace8415193eebc52cedcec64
|
@ -459,7 +459,7 @@ class CameraActivity : BaseActivity(), SensorOrientationListener.Listener {
|
||||
videoCapture?.startRecording(VideoCapture.OutputFileOptions(object : SeekableWriter {
|
||||
var offset = 0L
|
||||
override fun write(byteArray: ByteArray) {
|
||||
offset += encryptedVolume.write(fileHandle, offset, byteArray, byteArray.size)
|
||||
offset += encryptedVolume.write(fileHandle, offset, byteArray, 0, byteArray.size.toLong())
|
||||
}
|
||||
override fun seek(offset: Long) {
|
||||
this.offset = offset
|
||||
|
@ -9,7 +9,6 @@ object ConstValues {
|
||||
const val CRYFS_LOCAL_STATE_DIR = "cryfsLocalState"
|
||||
const val SORT_ORDER_KEY = "sort_order"
|
||||
val FAKE_URI: Uri = Uri.parse("fakeuri://droidfs")
|
||||
const val MAX_KERNEL_WRITE = 128*1024
|
||||
const val WIPE_PASSES = 2
|
||||
const val IO_BUFF_SIZE = 16384
|
||||
const val SLIDESHOW_DELAY: Long = 4000
|
||||
|
@ -131,10 +131,10 @@ class FileOperationService : Service() {
|
||||
if (dstFileHandle != -1L) {
|
||||
var offset: Long = 0
|
||||
val ioBuffer = ByteArray(ConstValues.IO_BUFF_SIZE)
|
||||
var length: Int
|
||||
while (remoteEncryptedVolume.read(srcFileHandle, ioBuffer, offset).also { length = it } > 0) {
|
||||
val written = encryptedVolume.write(dstFileHandle, offset, ioBuffer, length).toLong()
|
||||
if (written == length.toLong()) {
|
||||
var length: Long
|
||||
while (remoteEncryptedVolume.read(srcFileHandle, offset, ioBuffer, 0, ioBuffer.size.toLong()).also { length = it.toLong() } > 0) {
|
||||
val written = encryptedVolume.write(dstFileHandle, offset, ioBuffer, 0, length).toLong()
|
||||
if (written == length) {
|
||||
offset += written
|
||||
} else {
|
||||
success = false
|
||||
|
@ -1,23 +1,29 @@
|
||||
package sushi.hardcore.droidfs.file_viewers
|
||||
|
||||
import android.net.Uri
|
||||
import com.google.android.exoplayer2.C
|
||||
import com.google.android.exoplayer2.upstream.DataSource
|
||||
import com.google.android.exoplayer2.upstream.DataSpec
|
||||
import com.google.android.exoplayer2.upstream.TransferListener
|
||||
import sushi.hardcore.droidfs.ConstValues
|
||||
import sushi.hardcore.droidfs.filesystems.EncryptedVolume
|
||||
import kotlin.math.ceil
|
||||
import kotlin.math.min
|
||||
|
||||
class EncryptedVolumeDataSource(private val encryptedVolume: EncryptedVolume, private val filePath: String): DataSource {
|
||||
private var fileHandle = -1L
|
||||
private var fileSize: Long = -1
|
||||
private var fileOffset: Long = 0
|
||||
private var bytesRemaining: Long = -1
|
||||
|
||||
override fun open(dataSpec: DataSpec): Long {
|
||||
fileOffset = dataSpec.position
|
||||
fileHandle = encryptedVolume.openFile(filePath)
|
||||
fileSize = encryptedVolume.getAttr(filePath)!!.size
|
||||
return fileSize
|
||||
fileOffset = dataSpec.position
|
||||
val fileSize = encryptedVolume.getAttr(filePath)!!.size
|
||||
bytesRemaining = if (dataSpec.length == C.LENGTH_UNSET.toLong()) {
|
||||
fileSize - fileOffset
|
||||
} else {
|
||||
min(fileSize, dataSpec.length)
|
||||
}
|
||||
return bytesRemaining
|
||||
}
|
||||
|
||||
override fun getUri(): Uri {
|
||||
@ -33,23 +39,18 @@ class EncryptedVolumeDataSource(private val encryptedVolume: EncryptedVolume, pr
|
||||
}
|
||||
|
||||
override fun read(buffer: ByteArray, offset: Int, readLength: Int): Int {
|
||||
if (fileOffset >= fileSize){
|
||||
return -1
|
||||
}
|
||||
var totalRead = 0
|
||||
for (i in 0 until ceil(readLength.toDouble()/ConstValues.MAX_KERNEL_WRITE).toInt()){
|
||||
val tmpReadLength = min(readLength-totalRead, ConstValues.MAX_KERNEL_WRITE)
|
||||
val tmpBuff = if (fileOffset+tmpReadLength > fileSize){
|
||||
ByteArray((fileSize-fileOffset).toInt())
|
||||
} else {
|
||||
ByteArray(tmpReadLength)
|
||||
}
|
||||
val read = encryptedVolume.read(fileHandle, tmpBuff, fileOffset)
|
||||
System.arraycopy(tmpBuff, 0, buffer, offset+totalRead, read)
|
||||
fileOffset += read
|
||||
totalRead += read
|
||||
}
|
||||
return totalRead
|
||||
val originalOffset = fileOffset
|
||||
while (fileOffset < originalOffset+readLength && encryptedVolume.read(
|
||||
fileHandle,
|
||||
fileOffset,
|
||||
buffer,
|
||||
offset+(fileOffset-originalOffset),
|
||||
(originalOffset+readLength)-fileOffset
|
||||
).also { fileOffset += it } > 0
|
||||
) {}
|
||||
val totalRead = fileOffset-originalOffset
|
||||
bytesRemaining -= totalRead
|
||||
return totalRead.toInt()
|
||||
}
|
||||
|
||||
class Factory(private val encryptedVolume: EncryptedVolume, private val filePath: String): DataSource.Factory {
|
||||
|
@ -70,23 +70,12 @@ class TextEditor: FileViewerActivity() {
|
||||
val content = editor.text.toString().toByteArray()
|
||||
val fileHandle = encryptedVolume.openFile(filePath)
|
||||
if (fileHandle != -1L) {
|
||||
val buff = ByteArrayInputStream(content)
|
||||
var offset: Long = 0
|
||||
val ioBuffer = ByteArray(ConstValues.IO_BUFF_SIZE)
|
||||
var length: Int
|
||||
while (buff.read(ioBuffer).also { length = it } > 0) {
|
||||
val written = encryptedVolume.write(fileHandle, offset, ioBuffer, length).toLong()
|
||||
if (written == length.toLong()) {
|
||||
offset += written
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
while (offset < content.size && encryptedVolume.write(fileHandle, offset, content, offset, content.size.toLong()).also { offset += it } > 0) {}
|
||||
if (offset == content.size.toLong()){
|
||||
success = encryptedVolume.truncate(filePath, offset)
|
||||
}
|
||||
encryptedVolume.closeFile(fileHandle)
|
||||
buff.close()
|
||||
}
|
||||
if (success){
|
||||
Toast.makeText(this, getString(R.string.file_saved), Toast.LENGTH_SHORT).show()
|
||||
|
@ -33,8 +33,8 @@ class CryfsVolume(private val fusePtr: Long): EncryptedVolume() {
|
||||
): Boolean
|
||||
private external fun nativeCreate(fusePtr: Long, path: String, mode: Int): Long
|
||||
private external fun nativeOpen(fusePtr: Long, path: String, flags: Int): Long
|
||||
private external fun nativeRead(fusePtr: Long, fileHandle: Long, buffer: ByteArray, offset: Long): Int
|
||||
private external fun nativeWrite(fusePtr: Long, fileHandle: Long, offset: Long, buffer: ByteArray, size: Int): Int
|
||||
private external fun nativeRead(fusePtr: Long, fileHandle: Long, fileOffset: Long, buffer: ByteArray, dstOffset: Long, length: Long): Int
|
||||
private external fun nativeWrite(fusePtr: Long, fileHandle: Long, fileOffset: Long, buffer: ByteArray, srcOffset: Long, length: Long): Int
|
||||
private external fun nativeTruncate(fusePtr: Long, path: String, size: Long): Boolean
|
||||
private external fun nativeDeleteFile(fusePtr: Long, path: String): Boolean
|
||||
private external fun nativeCloseFile(fusePtr: Long, fileHandle: Long): Boolean
|
||||
@ -101,12 +101,12 @@ class CryfsVolume(private val fusePtr: Long): EncryptedVolume() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun read(fileHandle: Long, buffer: ByteArray, offset: Long): Int {
|
||||
return nativeRead(fusePtr, fileHandle, buffer, offset)
|
||||
override fun read(fileHandle: Long, fileOffset: Long, buffer: ByteArray, dstOffset: Long, length: Long): Int {
|
||||
return nativeRead(fusePtr, fileHandle, fileOffset, buffer, dstOffset, length)
|
||||
}
|
||||
|
||||
override fun write(fileHandle: Long, offset: Long, buffer: ByteArray, size: Int): Int {
|
||||
return nativeWrite(fusePtr, fileHandle, offset, buffer, size)
|
||||
override fun write(fileHandle: Long, fileOffset: Long, buffer: ByteArray, srcOffset: Long, length: Long): Int {
|
||||
return nativeWrite(fusePtr, fileHandle, fileOffset, buffer, srcOffset, length)
|
||||
}
|
||||
|
||||
override fun truncate(path: String, size: Long): Boolean {
|
||||
|
@ -74,8 +74,8 @@ abstract class EncryptedVolume: Parcelable {
|
||||
override fun describeContents() = 0
|
||||
|
||||
abstract fun openFile(path: String): Long
|
||||
abstract fun read(fileHandle: Long, buffer: ByteArray, offset: Long): Int
|
||||
abstract fun write(fileHandle: Long, offset: Long, buffer: ByteArray, size: Int): Int
|
||||
abstract fun read(fileHandle: Long, fileOffset: Long, buffer: ByteArray, dstOffset: Long, length: Long): Int
|
||||
abstract fun write(fileHandle: Long, fileOffset: Long, buffer: ByteArray, srcOffset: Long, length: Long): Int
|
||||
abstract fun closeFile(fileHandle: Long): Boolean
|
||||
// Due to gocryptfs internals, truncate requires the file to be open before it is called
|
||||
abstract fun truncate(path: String, size: Long): Boolean
|
||||
@ -96,7 +96,7 @@ abstract class EncryptedVolume: Parcelable {
|
||||
var offset: Long = 0
|
||||
val ioBuffer = ByteArray(ConstValues.IO_BUFF_SIZE)
|
||||
var length: Int
|
||||
while (read(fileHandle, ioBuffer, offset).also { length = it } > 0) {
|
||||
while (read(fileHandle, offset, ioBuffer, 0, ioBuffer.size.toLong()).also { length = it } > 0) {
|
||||
os.write(ioBuffer, 0, length)
|
||||
offset += length.toLong()
|
||||
}
|
||||
@ -132,10 +132,10 @@ abstract class EncryptedVolume: Parcelable {
|
||||
var success = true
|
||||
var offset: Long = 0
|
||||
val ioBuffer = ByteArray(ConstValues.IO_BUFF_SIZE)
|
||||
var length: Int
|
||||
while (inputStream.read(ioBuffer).also { length = it } > 0) {
|
||||
val written = write(dstfileHandle, offset, ioBuffer, length).toLong()
|
||||
if (written == length.toLong()) {
|
||||
var length: Long
|
||||
while (inputStream.read(ioBuffer).also { length = it.toLong() } > 0) {
|
||||
val written = write(dstfileHandle, offset, ioBuffer, 0, length).toLong()
|
||||
if (written == length) {
|
||||
offset += written
|
||||
} else {
|
||||
inputStream.close()
|
||||
@ -174,12 +174,7 @@ abstract class EncryptedVolume: Parcelable {
|
||||
Pair(null, 3)
|
||||
} else {
|
||||
var offset: Long = 0
|
||||
val ioBuffer = ByteArray(ConstValues.IO_BUFF_SIZE)
|
||||
var length: Int
|
||||
while (read(fileHandle, ioBuffer, offset).also { length = it } > 0) {
|
||||
System.arraycopy(ioBuffer, 0, fileBuff, offset.toInt(), length)
|
||||
offset += length.toLong()
|
||||
}
|
||||
while (offset < fileSize && read(fileHandle, offset, fileBuff, offset, fileSize-offset).also { offset += it } > 0) {}
|
||||
closeFile(fileHandle)
|
||||
if (offset == fileBuff.size.toLong()) {
|
||||
Pair(fileBuff, 0)
|
||||
|
@ -2,6 +2,7 @@ package sushi.hardcore.droidfs.filesystems
|
||||
|
||||
import android.os.Parcel
|
||||
import sushi.hardcore.droidfs.explorers.ExplorerElement
|
||||
import kotlin.math.min
|
||||
|
||||
class GocryptfsVolume(private val sessionID: Int): EncryptedVolume() {
|
||||
private external fun native_close(sessionID: Int)
|
||||
@ -9,8 +10,8 @@ class GocryptfsVolume(private val sessionID: Int): EncryptedVolume() {
|
||||
private external fun native_list_dir(sessionID: Int, dir_path: String): MutableList<ExplorerElement>?
|
||||
private external fun native_open_read_mode(sessionID: Int, file_path: String): Int
|
||||
private external fun native_open_write_mode(sessionID: Int, file_path: String, mode: Int): Int
|
||||
private external fun native_read_file(sessionID: Int, handleID: Int, offset: Long, buff: ByteArray): Int
|
||||
private external fun native_write_file(sessionID: Int, handleID: Int, offset: Long, buff: ByteArray, buff_size: Int): Int
|
||||
private external fun native_read_file(sessionID: Int, handleID: Int, fileOffset: Long, buff: ByteArray, dstOffset: Long, length: Int): Int
|
||||
private external fun native_write_file(sessionID: Int, handleID: Int, fileOffset: Long, buff: ByteArray, srcOffset: Long, length: Int): Int
|
||||
private external fun native_truncate(sessionID: Int, path: String, offset: Long): Boolean
|
||||
private external fun native_close_file(sessionID: Int, handleID: Int)
|
||||
private external fun native_remove_file(sessionID: Int, file_path: String): Boolean
|
||||
@ -22,6 +23,7 @@ class GocryptfsVolume(private val sessionID: Int): EncryptedVolume() {
|
||||
companion object {
|
||||
const val KeyLen = 32
|
||||
const val ScryptDefaultLogN = 16
|
||||
const val MAX_KERNEL_WRITE = 128*1024
|
||||
const val CONFIG_FILE_NAME = "gocryptfs.conf"
|
||||
external fun createVolume(root_cipher_dir: String, password: ByteArray, plainTextNames: Boolean, xchacha: Int, logN: Int, creator: String, returnedHash: ByteArray?): Boolean
|
||||
private external fun nativeInit(root_cipher_dir: String, password: ByteArray?, givenHash: ByteArray?, returnedHash: ByteArray?): Int
|
||||
@ -53,8 +55,8 @@ class GocryptfsVolume(private val sessionID: Int): EncryptedVolume() {
|
||||
return native_open_write_mode(sessionID, path, 0).toLong()
|
||||
}
|
||||
|
||||
override fun read(fileHandle: Long, buffer: ByteArray, offset: Long): Int {
|
||||
return native_read_file(sessionID, fileHandle.toInt(), offset, buffer)
|
||||
override fun read(fileHandle: Long, fileOffset: Long, buffer: ByteArray, dstOffset: Long, length: Long): Int {
|
||||
return native_read_file(sessionID, fileHandle.toInt(), fileOffset, buffer, dstOffset, min(length.toInt(), MAX_KERNEL_WRITE))
|
||||
}
|
||||
|
||||
override fun readDir(path: String): MutableList<ExplorerElement>? {
|
||||
@ -91,8 +93,8 @@ class GocryptfsVolume(private val sessionID: Int): EncryptedVolume() {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun write(fileHandle: Long, offset: Long, buffer: ByteArray, size: Int): Int {
|
||||
return native_write_file(sessionID, fileHandle.toInt(), offset, buffer, size)
|
||||
override fun write(fileHandle: Long, fileOffset: Long, buffer: ByteArray, srcOffset: Long, length: Long): Int {
|
||||
return native_write_file(sessionID, fileHandle.toInt(), fileOffset, buffer, srcOffset, min(length.toInt(), MAX_KERNEL_WRITE))
|
||||
}
|
||||
|
||||
override fun truncate(path: String, size: Long): Boolean {
|
||||
|
@ -293,12 +293,12 @@ Java_sushi_hardcore_droidfs_filesystems_GocryptfsVolume_native_1open_1write_1mod
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_sushi_hardcore_droidfs_filesystems_GocryptfsVolume_native_1write_1file(JNIEnv *env, jobject thiz,
|
||||
jint sessionID, jint handleID, jlong offset,
|
||||
jbyteArray jbuff, jint buff_size) {
|
||||
jint sessionID, jint handleID, jlong file_offset,
|
||||
jbyteArray jbuff, jlong src_offset, jint length) {
|
||||
jbyte* buff = (*env)->GetByteArrayElements(env, jbuff, NULL);
|
||||
GoSlice go_buff = {buff, buff_size, buff_size};
|
||||
GoSlice go_buff = {buff+src_offset, length, length};
|
||||
|
||||
int written = gcf_write_file(sessionID, handleID, offset, go_buff);
|
||||
int written = gcf_write_file(sessionID, handleID, file_offset, go_buff);
|
||||
|
||||
(*env)->ReleaseByteArrayElements(env, jbuff, buff, 0);
|
||||
|
||||
@ -307,13 +307,12 @@ Java_sushi_hardcore_droidfs_filesystems_GocryptfsVolume_native_1write_1file(JNIE
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_sushi_hardcore_droidfs_filesystems_GocryptfsVolume_native_1read_1file(JNIEnv *env, jobject thiz,
|
||||
jint sessionID, jint handleID, jlong offset,
|
||||
jbyteArray jbuff) {
|
||||
const size_t buff_size = (*env)->GetArrayLength(env, jbuff);
|
||||
jint sessionID, jint handleID, jlong file_offset,
|
||||
jbyteArray jbuff, jlong dst_offset, jint length) {
|
||||
jbyte* buff = (*env)->GetByteArrayElements(env, jbuff, NULL);
|
||||
GoSlice go_buff = {buff, buff_size, buff_size};
|
||||
GoSlice go_buff = {buff+dst_offset, length, length};
|
||||
|
||||
int read = gcf_read_file(sessionID, handleID, offset, go_buff);
|
||||
int read = gcf_read_file(sessionID, handleID, file_offset, go_buff);
|
||||
|
||||
(*env)->ReleaseByteArrayElements(env, jbuff, buff, 0);
|
||||
return read;
|
||||
|
@ -35,10 +35,15 @@ Java_sushi_hardcore_droidfs_filesystems_CryfsVolume_00024Companion_nativeOpen(JN
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_sushi_hardcore_droidfs_filesystems_CryfsVolume_00024Companion_nativeRead(JNIEnv *env, jobject thiz,
|
||||
jlong fuse_ptr, jlong file_handle,
|
||||
jbyteArray buffer, jlong offset) {
|
||||
return cryfs_read(env, fuse_ptr, file_handle, buffer, offset);
|
||||
Java_sushi_hardcore_droidfs_filesystems_CryfsVolume_00024Companion_nativeRead(JNIEnv *env,
|
||||
jobject thiz,
|
||||
jlong fuse_ptr,
|
||||
jlong file_handle,
|
||||
jlong file_offset,
|
||||
jbyteArray buffer,
|
||||
jlong dst_offset,
|
||||
jlong length) {
|
||||
return cryfs_read(env, fuse_ptr, file_handle, file_offset, buffer, dst_offset, length);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
@ -46,10 +51,11 @@ Java_sushi_hardcore_droidfs_filesystems_CryfsVolume_00024Companion_nativeWrite(J
|
||||
jobject thiz,
|
||||
jlong fuse_ptr,
|
||||
jlong file_handle,
|
||||
jlong offset,
|
||||
jlong file_offset,
|
||||
jbyteArray buffer,
|
||||
jint size) {
|
||||
return cryfs_write(env, fuse_ptr, file_handle, offset, buffer, size);
|
||||
jlong src_offset,
|
||||
jlong length) {
|
||||
return cryfs_write(env, fuse_ptr, file_handle, file_offset, buffer, src_offset, length);
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
|
Loading…
Reference in New Issue
Block a user