Skip to content
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
12 changes: 8 additions & 4 deletions app/src/main/java/com/chiller3/rsaf/rclone/Authorizer.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Andrew Gunnerson
* SPDX-FileCopyrightText: 2023-2026 Andrew Gunnerson
* SPDX-License-Identifier: GPL-3.0-only
*/

Expand Down Expand Up @@ -49,14 +49,18 @@ object Authorizer {
.drop(2)

private fun logAsIfGo(msg: String) {
Log.i(GO_TAG, msg)
// This is intentionally logging at the error level because HarmonyOS devices seem to only
// preserve error logs.
Log.e(GO_TAG, msg)
}

private fun authorizeBlockingLocked(cmd: String, listener: AuthorizeListener) {
val args = parseCmd(cmd)

Log.d(TAG, "Starting logcat")
val logcat = ProcessBuilder("logcat", "-v", "raw", "*:S", "$GO_TAG:V")
// We intentionally only capture error logs so that the HarmonyOS behavior is used
// everywhere for easier testing.
val logcat = ProcessBuilder("logcat", "-v", "raw", "*:S", "$GO_TAG:E")
.redirectOutput(ProcessBuilder.Redirect.PIPE)
.redirectErrorStream(true)
.start()
Expand All @@ -79,7 +83,7 @@ object Authorizer {

try {
processLogs(logcat.inputStream, markerNow, listener)
} catch (e: Exception) {
} catch (_: Exception) {
cancelServer()
} finally {
server.join()
Expand Down
31 changes: 29 additions & 2 deletions rcbridge/rcbridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ var (
vfsInstances = make(map[string]*vfs.VFS)
vfsOptValidKeys = make(map[string]bool)
vfsOptStringKeys = make(map[string]bool)
stdoutHijackLock goSync.Mutex
)

func init() {
Expand Down Expand Up @@ -1307,15 +1308,41 @@ func (rbfile *RbFile) GetSize(errOut *RbError) int64 {
// None of the underlying functions are available outside of the oauthutil
// package and the higher level functions print to stdout and can only be killed
// by sending a bad request to it. But since that's what we have to work with,
// we'll deal with it on the Android side by parsing logcat.
// we'll deal with it.
//
// There are two pieces of information we need: the local server URL and the
// oauth refresh token once authorized. The former can only be obtained via
// logcat since oauthutil.configSetup() uses fs.Logf(). The latter gets printed
// to stdout, which normally shows up in logcat due to gomobile, but some OS's
// like HarmonyOS only show messages with error priority. We work around this by
// temporarily sending stdout to stderr.
func RbAuthorize(argsNullSep string, errOut *RbError) bool {
stdoutHijackLock.Lock()
defer stdoutHijackLock.Unlock()

var args = strings.Split(argsNullSep, "\x00")

err := config.Authorize(context.Background(), args, true, "")
origStdout, err := syscall.Dup(int(os.Stdout.Fd()))
if err != nil {
assignError(errOut, err, syscall.EIO)
return false
}
defer syscall.Close(origStdout)

if err = syscall.Dup3(int(os.Stderr.Fd()), int(os.Stdout.Fd()), 0); err != nil {
assignError(errOut, err, syscall.EIO)
return false
}

if err = config.Authorize(context.Background(), args, true, ""); err != nil {
assignError(errOut, err, syscall.EIO)
return false
}

if err = syscall.Dup3(int(origStdout), int(os.Stdout.Fd()), 0); err != nil {
assignError(errOut, err, syscall.EIO)
return false
}

return true
}
Expand Down