summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog.android9
-rw-r--r--java/org/gnu/emacs/EmacsNative.java4
-rw-r--r--java/org/gnu/emacs/EmacsSafThread.java37
-rw-r--r--src/androidvfs.c8
4 files changed, 57 insertions, 1 deletions
diff --git a/ChangeLog.android b/ChangeLog.android
index 689482d2f1a..82ab75b40c1 100644
--- a/ChangeLog.android
+++ b/ChangeLog.android
@@ -1,11 +1,20 @@
2023-08-06 Po Lu <luangruo@yahoo.com>
+ * java/org/gnu/emacs/EmacsSafThread.java (openDocument1): If
+ initially opening with rwt, verify the file descriptor is really
+ writable; if not, resort to rw and truncating the file descriptor
+ by hand instead.
+
+ * src/androidvfs.c (NATIVE_NAME (ftruncate)): New function.
+ Truncate file descriptor and return whether that was successful.
+
* src/androidvfs.c (android_saf_tree_chmod): Repair file access
permissions allowed within FLAGS.
2023-08-05 Po Lu <luangruo@yahoo.com>
* doc/lispref/commands.texi (Touchscreen Events): Fix typo.
+
* lisp/subr.el (y-or-n-p): Don't call set-text-conversion-style
when not present.
diff --git a/java/org/gnu/emacs/EmacsNative.java b/java/org/gnu/emacs/EmacsNative.java
index 7d72a9f192e..fae0ba98f86 100644
--- a/java/org/gnu/emacs/EmacsNative.java
+++ b/java/org/gnu/emacs/EmacsNative.java
@@ -274,6 +274,10 @@ public final class EmacsNative
operations. */
public static native void safPostRequest ();
+ /* Detect and return FD is writable. FD may be truncated to 0 bytes
+ in the process. */
+ public static native boolean ftruncate (int fd);
+
static
{
/* Older versions of Android cannot link correctly with shared
diff --git a/java/org/gnu/emacs/EmacsSafThread.java b/java/org/gnu/emacs/EmacsSafThread.java
index 29cd3fa6bc7..3ae3c0839ce 100644
--- a/java/org/gnu/emacs/EmacsSafThread.java
+++ b/java/org/gnu/emacs/EmacsSafThread.java
@@ -24,6 +24,7 @@ import java.util.HashMap;
import java.util.Iterator;
import java.io.FileNotFoundException;
+import java.io.IOException;
import android.content.ContentResolver;
import android.database.Cursor;
@@ -1597,6 +1598,42 @@ public final class EmacsSafThread extends HandlerThread
= resolver.openFileDescriptor (documentUri, mode,
signal);
+ /* If a writable file descriptor is requested and TRUNCATE is set,
+ then probe the file descriptor to detect if it is actually
+ readable. If not, close this file descriptor and reopen it
+ with MODE set to rw; some document providers granting access to
+ Samba shares don't implement rwt, but these document providers
+ invariably truncate the file opened even when the mode is
+ merely rw.
+
+ This may be ascribed to a mix-up in Android's documentation
+ regardin DocumentsProvider: the `openDocument' function is only
+ documented to accept r or rw, whereas the default
+ implementation of the `openFile' function (which documents rwt)
+ delegates to `openDocument'. */
+
+ if (write && truncate && fileDescriptor != null
+ && !EmacsNative.ftruncate (fileDescriptor.getFd ()))
+ {
+ try
+ {
+ fileDescriptor.closeWithError ("File descriptor requested"
+ + " is not writable");
+ }
+ catch (IOException e)
+ {
+ Log.w (TAG, "Leaking unclosed file descriptor " + e);
+ }
+
+ fileDescriptor
+ = resolver.openFileDescriptor (documentUri, "rw", signal);
+
+ /* Try to truncate fileDescriptor just to stay on the safe
+ side. */
+ if (fileDescriptor != null)
+ EmacsNative.ftruncate (fileDescriptor.getFd ());
+ }
+
/* Every time a document is opened, remove it from the file status
cache. */
toplevel = getCache (treeUri);
diff --git a/src/androidvfs.c b/src/androidvfs.c
index dc5097f463e..d6daff481b0 100644
--- a/src/androidvfs.c
+++ b/src/androidvfs.c
@@ -5605,7 +5605,7 @@ android_saf_file_open (struct android_vnode *vnode, int flags,
/* Open a parcel file descriptor according to flags. */
method = service_class.open_document;
- trunc = flags & O_TRUNC;
+ trunc = (flags & O_TRUNC);
write = ((flags & O_RDWR) == O_RDWR || (flags & O_WRONLY));
inside_saf_critical_section = true;
descriptor
@@ -6121,6 +6121,12 @@ NATIVE_NAME (safPostRequest) (JNIEnv *env, jobject object)
sem_post (&saf_completion_sem);
}
+JNIEXPORT jboolean JNICALL
+NATIVE_NAME (ftruncate) (JNIEnv *env, jobject object, jint fd)
+{
+ return ftruncate (fd, 0) != -1;
+}
+
#ifdef __clang__
#pragma clang diagnostic pop
#else /* GNUC */