summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPo Lu <luangruo@yahoo.com>2024-05-10 09:05:54 +0800
committerPo Lu <luangruo@yahoo.com>2024-05-10 09:05:54 +0800
commitc900c707e8f3075dfe57c39a8a6363ba4575035f (patch)
tree4d2ce9fe218b9e0158229aad1aff9140903d4db3
parentd335f28aa9bfb85d0e35b838ca867d97ebe5b974 (diff)
downloademacs-c900c707e8f3075dfe57c39a8a6363ba4575035f.tar.gz
Fix earlier change to content URI resolution on Android
* java/org/gnu/emacs/EmacsService.java (openContentUri): Return -1 if fd be NULL. * src/androidvfs.c (android_authority_open): Detect SecurityException and suchlike. (android_vfs_init): Initialize exception classes on Android 4.4.
-rw-r--r--java/org/gnu/emacs/EmacsService.java5
-rw-r--r--src/androidvfs.c221
2 files changed, 116 insertions, 110 deletions
diff --git a/java/org/gnu/emacs/EmacsService.java b/java/org/gnu/emacs/EmacsService.java
index 5548748ddfa..1e5f72eed37 100644
--- a/java/org/gnu/emacs/EmacsService.java
+++ b/java/org/gnu/emacs/EmacsService.java
@@ -968,7 +968,7 @@ public final class EmacsService extends Service
string; make it writable if WRITABLE, and readable if READABLE.
Truncate the file if TRUNCATE.
- Value is the resulting file descriptor or an exception will be
+ Value is the resulting file descriptor, -1, or an exception will be
raised. */
public int
@@ -999,6 +999,9 @@ public final class EmacsService extends Service
minimum requirement for access to /content/by-authority. */
fd = resolver.openFileDescriptor (Uri.parse (uri), mode);
+ if (fd == null)
+ return -1;
+
i = fd.detachFd ();
fd.close ();
diff --git a/src/androidvfs.c b/src/androidvfs.c
index c326896d4c3..284b1370549 100644
--- a/src/androidvfs.c
+++ b/src/androidvfs.c
@@ -3023,6 +3023,104 @@ android_check_content_access (const char *uri, int mode)
+/* Functions shared by authority and SAF nodes. */
+
+/* Check for JNI exceptions, clear them, and set errno accordingly.
+ Also, free each of the N local references given as arguments if an
+ exception takes place.
+
+ Value is 1 if an exception has taken place, 0 otherwise.
+
+ If the exception thrown derives from FileNotFoundException, set
+ errno to ENOENT.
+
+ If the exception thrown derives from SecurityException, set errno
+ to EACCES.
+
+ If the exception thrown derives from OperationCanceledException,
+ set errno to EINTR.
+
+ If the exception thrown derives from UnsupportedOperationException,
+ set errno to ENOSYS.
+
+ If the exception thrown derives from OutOfMemoryException, call
+ `memory_full'.
+
+ If the exception thrown is anything else, set errno to EIO. */
+
+static int
+android_saf_exception_check (int n, ...)
+{
+ jthrowable exception;
+ JNIEnv *env;
+ va_list ap;
+ int new_errno;
+
+ env = android_java_env;
+ va_start (ap, n);
+
+ /* First, check for an exception. */
+
+ if (!(*env)->ExceptionCheck (env))
+ {
+ /* No exception has taken place. Return 0. */
+ va_end (ap);
+ return 0;
+ }
+
+ /* Print the exception. */
+ (*env)->ExceptionDescribe (env);
+
+ exception = (*env)->ExceptionOccurred (env);
+
+ if (!exception)
+ /* JNI couldn't return a local reference to the exception. */
+ memory_full (0);
+
+ /* Clear the exception, making it safe to subsequently call other
+ JNI functions. */
+ (*env)->ExceptionClear (env);
+
+ /* Delete each of the N arguments. */
+
+ while (n > 0)
+ {
+ ANDROID_DELETE_LOCAL_REF (va_arg (ap, jobject));
+ n--;
+ }
+
+ /* Now set errno or signal memory_full as required. */
+
+ if ((*env)->IsInstanceOf (env, (jobject) exception,
+ file_not_found_exception))
+ new_errno = ENOENT;
+ else if ((*env)->IsInstanceOf (env, (jobject) exception,
+ security_exception))
+ new_errno = EACCES;
+ else if ((*env)->IsInstanceOf (env, (jobject) exception,
+ operation_canceled_exception))
+ new_errno = EINTR;
+ else if ((*env)->IsInstanceOf (env, (jobject) exception,
+ unsupported_operation_exception))
+ new_errno = ENOSYS;
+ else if ((*env)->IsInstanceOf (env, (jobject) exception,
+ out_of_memory_error))
+ {
+ ANDROID_DELETE_LOCAL_REF ((jobject) exception);
+ memory_full (0);
+ }
+ else
+ new_errno = EIO;
+
+ /* expression is still a local reference! */
+ ANDROID_DELETE_LOCAL_REF ((jobject) exception);
+ errno = new_errno;
+ va_end (ap);
+ return 1;
+}
+
+
+
/* Content authority-based vnode implementation.
/content/by-authority is a simple vnode implementation that converts
@@ -3201,7 +3299,9 @@ android_authority_open (struct android_vnode *vnode, int flags,
(jboolean) !(mode & O_WRONLY),
(jboolean) ((mode & O_TRUNC)
!= 0));
- android_exception_check_1 (string);
+ if (android_saf_exception_check (1, string))
+ return -1;
+ ANDROID_DELETE_LOCAL_REF (string);
/* If fd is -1, just assume that the file does not exist,
and return -1 with errno set to ENOENT. */
@@ -3209,18 +3309,12 @@ android_authority_open (struct android_vnode *vnode, int flags,
if (fd == -1)
{
errno = ENOENT;
- goto skip;
+ return -1;
}
if (mode & O_CLOEXEC)
android_close_on_exec (fd);
- skip:
- ANDROID_DELETE_LOCAL_REF (string);
-
- if (fd == -1)
- return -1;
-
*fd_return = fd;
return 0;
}
@@ -4089,100 +4183,6 @@ android_saf_root_get_directory (int dirfd)
thread. */
static bool inside_saf_critical_section;
-/* Check for JNI exceptions, clear them, and set errno accordingly.
- Also, free each of the N local references given as arguments if an
- exception takes place.
-
- Value is 1 if an exception has taken place, 0 otherwise.
-
- If the exception thrown derives from FileNotFoundException, set
- errno to ENOENT.
-
- If the exception thrown derives from SecurityException, set errno
- to EACCES.
-
- If the exception thrown derives from OperationCanceledException,
- set errno to EINTR.
-
- If the exception thrown derives from UnsupportedOperationException,
- set errno to ENOSYS.
-
- If the exception thrown derives from OutOfMemoryException, call
- `memory_full'.
-
- If the exception thrown is anything else, set errno to EIO. */
-
-static int
-android_saf_exception_check (int n, ...)
-{
- jthrowable exception;
- JNIEnv *env;
- va_list ap;
- int new_errno;
-
- env = android_java_env;
- va_start (ap, n);
-
- /* First, check for an exception. */
-
- if (!(*env)->ExceptionCheck (env))
- {
- /* No exception has taken place. Return 0. */
- va_end (ap);
- return 0;
- }
-
- /* Print the exception. */
- (*env)->ExceptionDescribe (env);
-
- exception = (*env)->ExceptionOccurred (env);
-
- if (!exception)
- /* JNI couldn't return a local reference to the exception. */
- memory_full (0);
-
- /* Clear the exception, making it safe to subsequently call other
- JNI functions. */
- (*env)->ExceptionClear (env);
-
- /* Delete each of the N arguments. */
-
- while (n > 0)
- {
- ANDROID_DELETE_LOCAL_REF (va_arg (ap, jobject));
- n--;
- }
-
- /* Now set errno or signal memory_full as required. */
-
- if ((*env)->IsInstanceOf (env, (jobject) exception,
- file_not_found_exception))
- new_errno = ENOENT;
- else if ((*env)->IsInstanceOf (env, (jobject) exception,
- security_exception))
- new_errno = EACCES;
- else if ((*env)->IsInstanceOf (env, (jobject) exception,
- operation_canceled_exception))
- new_errno = EINTR;
- else if ((*env)->IsInstanceOf (env, (jobject) exception,
- unsupported_operation_exception))
- new_errno = ENOSYS;
- else if ((*env)->IsInstanceOf (env, (jobject) exception,
- out_of_memory_error))
- {
- ANDROID_DELETE_LOCAL_REF ((jobject) exception);
- memory_full (0);
- }
- else
- new_errno = EIO;
-
- /* expression is still a local reference! */
- ANDROID_DELETE_LOCAL_REF ((jobject) exception);
- errno = new_errno;
- va_end (ap);
- return 1;
-}
-
/* Return file status for the document designated by ID_NAME within
the document tree identified by URI_NAME.
@@ -6883,15 +6883,9 @@ android_vfs_init (JNIEnv *env, jobject manager)
eassert (java_string_class);
(*env)->DeleteLocalRef (env, old);
- /* And initialize those used on Android 5.0 and later. */
-
- if (android_get_current_api_level () < 21)
+ if (android_get_current_api_level () < 19)
return;
- android_init_cursor_class (env);
- android_init_entry_class (env);
- android_init_fd_class (env);
-
/* Initialize each of the exception classes used by
`android_saf_exception_check'. */
@@ -6920,6 +6914,15 @@ android_vfs_init (JNIEnv *env, jobject manager)
(*env)->DeleteLocalRef (env, old);
eassert (out_of_memory_error);
+ /* And initialize those used on Android 5.0 and later. */
+
+ if (android_get_current_api_level () < 21)
+ return;
+
+ android_init_cursor_class (env);
+ android_init_entry_class (env);
+ android_init_fd_class (env);
+
/* Initialize the semaphore used to wait for SAF operations to
complete. */