From: Po Lu Date: Sun, 6 Aug 2023 13:45:29 +0000 (+0800) Subject: Update Android port X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=7873369338ee0159ca285153fd4592cbcff65d7a;p=emacs.git Update Android port * java/org/gnu/emacs/EmacsNative.java: Declare ftruncate. * 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. --- 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 + * 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 * 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 */