[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
master d35ead5bd8a 2/3: Utilize more frequently supported file access mo
From: |
Po Lu |
Subject: |
master d35ead5bd8a 2/3: Utilize more frequently supported file access modes |
Date: |
Tue, 8 Aug 2023 01:50:12 -0400 (EDT) |
branch: master
commit d35ead5bd8a2630c34a38e02d4689e682b0e1ba9
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>
Utilize more frequently supported file access modes
* java/org/gnu/emacs/EmacsSafThread.java (openDocument1): Use
plain r or w where possible, as the fileio stuff is now better
prepared for FIFOs.
(openDocument): New argument READ.
* java/org/gnu/emacs/EmacsService.java (openDocument): New
argument READ.
* src/android.c (android_init_emacs_service): Adjust
correspondingly.
* src/androidvfs.c (android_saf_file_open): Don't support
O_APPEND. Pass read as well as trunc and write.
---
java/org/gnu/emacs/EmacsSafThread.java | 58 ++++++++++++++++++++--------------
java/org/gnu/emacs/EmacsService.java | 20 ++++++------
src/android.c | 2 +-
src/androidvfs.c | 46 ++++++++++++++++++++++++---
4 files changed, 85 insertions(+), 41 deletions(-)
diff --git a/java/org/gnu/emacs/EmacsSafThread.java
b/java/org/gnu/emacs/EmacsSafThread.java
index 3ae3c0839ce..9f5d7f3d0cf 100644
--- a/java/org/gnu/emacs/EmacsSafThread.java
+++ b/java/org/gnu/emacs/EmacsSafThread.java
@@ -1565,8 +1565,9 @@ public final class EmacsSafThread extends HandlerThread
signal. */
public ParcelFileDescriptor
- openDocument1 (String uri, String documentId, boolean write,
- boolean truncate, CancellationSignal signal)
+ openDocument1 (String uri, String documentId, boolean read,
+ boolean write, boolean truncate,
+ CancellationSignal signal)
throws Throwable
{
Uri treeUri, documentUri;
@@ -1586,10 +1587,19 @@ public final class EmacsSafThread extends HandlerThread
if (write)
{
- if (truncate)
- mode = "rwt";
+ if (read)
+ {
+ if (truncate)
+ mode = "rwt";
+ else
+ mode = "rw";
+ }
else
- mode = "rw";
+ /* Set mode to w when WRITE && !READ, disregarding TRUNCATE.
+ In contradiction with the ContentResolver documentation,
+ document providers seem to truncate files whenever w is
+ specified, at least superficially. */
+ mode = "w";
}
else
mode = "r";
@@ -1597,14 +1607,15 @@ public final class EmacsSafThread extends HandlerThread
fileDescriptor
= resolver.openFileDescriptor (documentUri, mode,
signal);
+ Log.d (TAG, "openDocument1: " + mode + " " + fileDescriptor);
- /* 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.
+ /* If a writable on-disk 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 w.
This may be ascribed to a mix-up in Android's documentation
regardin DocumentsProvider: the `openDocument' function is only
@@ -1612,7 +1623,7 @@ public final class EmacsSafThread extends HandlerThread
implementation of the `openFile' function (which documents rwt)
delegates to `openDocument'. */
- if (write && truncate && fileDescriptor != null
+ if (read && write && truncate && fileDescriptor != null
&& !EmacsNative.ftruncate (fileDescriptor.getFd ()))
{
try
@@ -1647,15 +1658,13 @@ public final class EmacsSafThread extends HandlerThread
TRUNCATE and the document already exists, truncate its contents
before returning.
- On Android 9.0 and earlier, always open the document in
- ``read-write'' mode; this instructs the document provider to
- return a seekable file that is stored on disk and returns correct
- file status.
+ If READ && WRITE, open the file under either the `rw' or `rwt'
+ access mode, which implies that the value must be a seekable
+ on-disk file. If WRITE && !READ or TRUNC && WRITE, also truncate
+ the file after it is opened.
- Under newer versions of Android, open the document in a
- non-writable mode if WRITE is false. This is possible because
- these versions allow Emacs to explicitly request a seekable
- on-disk file.
+ If only READ or WRITE is set, value may be a non-seekable FIFO or
+ one end of a socket pair.
Value is NULL upon failure or a parcel file descriptor upon
success. Call `ParcelFileDescriptor.close' on this file
@@ -1667,7 +1676,8 @@ public final class EmacsSafThread extends HandlerThread
public ParcelFileDescriptor
openDocument (final String uri, final String documentId,
- final boolean write, final boolean truncate)
+ final boolean read, final boolean write,
+ final boolean truncate)
{
Object tem;
@@ -1677,8 +1687,8 @@ public final class EmacsSafThread extends HandlerThread
runObject (CancellationSignal signal)
throws Throwable
{
- return openDocument1 (uri, documentId, write, truncate,
- signal);
+ return openDocument1 (uri, documentId, read,
+ write, truncate, signal);
}
});
diff --git a/java/org/gnu/emacs/EmacsService.java
b/java/org/gnu/emacs/EmacsService.java
index d91d8f66009..14ff2cce98f 100644
--- a/java/org/gnu/emacs/EmacsService.java
+++ b/java/org/gnu/emacs/EmacsService.java
@@ -1537,15 +1537,13 @@ public final class EmacsService extends Service
TRUNCATE and the document already exists, truncate its contents
before returning.
- On Android 9.0 and earlier, always open the document in
- ``read-write'' mode; this instructs the document provider to
- return a seekable file that is stored on disk and returns correct
- file status.
+ If READ && WRITE, open the file under either the `rw' or `rwt'
+ access mode, which implies that the value must be a seekable
+ on-disk file. If TRUNC && WRITE, also truncate the file after it
+ is opened.
- Under newer versions of Android, open the document in a
- non-writable mode if WRITE is false. This is possible because
- these versions allow Emacs to explicitly request a seekable
- on-disk file.
+ If only READ or WRITE is set, value may be a non-seekable FIFO or
+ one end of a socket pair.
Value is NULL upon failure or a parcel file descriptor upon
success. Call `ParcelFileDescriptor.close' on this file
@@ -1555,8 +1553,8 @@ public final class EmacsService extends Service
UnsupportedOperationException may be thrown upon failure. */
public ParcelFileDescriptor
- openDocument (String uri, String documentId, boolean write,
- boolean truncate)
+ openDocument (String uri, String documentId,
+ boolean read, boolean write, boolean truncate)
{
/* Start the thread used to run SAF requests if it isn't already
running. */
@@ -1567,7 +1565,7 @@ public final class EmacsService extends Service
storageThread.start ();
}
- return storageThread.openDocument (uri, documentId, write,
+ return storageThread.openDocument (uri, documentId, read, write,
truncate);
}
diff --git a/src/android.c b/src/android.c
index bd19107f53a..7f263bc83d1 100644
--- a/src/android.c
+++ b/src/android.c
@@ -1574,7 +1574,7 @@ android_init_emacs_service (void)
"(Landroid/database/Cursor;)Lorg/gnu/emacs/"
"EmacsDirectoryEntry;");
FIND_METHOD (open_document, "openDocument",
- "(Ljava/lang/String;Ljava/lang/String;ZZ)"
+ "(Ljava/lang/String;Ljava/lang/String;ZZZ)"
"Landroid/os/ParcelFileDescriptor;");
FIND_METHOD (create_document, "createDocument",
"(Ljava/lang/String;Ljava/lang/String;"
diff --git a/src/androidvfs.c b/src/androidvfs.c
index 4234e337acb..0ee555c0ad4 100644
--- a/src/androidvfs.c
+++ b/src/androidvfs.c
@@ -5590,7 +5590,7 @@ android_saf_file_open (struct android_vnode *vnode, int
flags,
struct android_saf_file_vnode *vp;
jobject uri, id, descriptor;
jmethodID method;
- jboolean trunc, write;
+ jboolean read, trunc, write;
jint fd;
struct android_parcel_fd *info;
struct stat statb;
@@ -5601,6 +5601,15 @@ android_saf_file_open (struct android_vnode *vnode, int
flags,
return -1;
}
+ /* O_APPEND isn't supported as a consequence of Android content
+ providers defaulting to truncating the file. */
+
+ if (flags & O_APPEND)
+ {
+ errno = EOPNOTSUPP;
+ return -1;
+ }
+
/* Build strings for both the URI and ID. */
vp = (struct android_saf_file_vnode *) vnode;
@@ -5611,18 +5620,43 @@ android_saf_file_open (struct android_vnode *vnode, int
flags,
vp->document_id);
android_exception_check_1 (uri);
- /* Open a parcel file descriptor according to flags. */
+ /* Open a parcel file descriptor according to flags. Documentation
+ for the SAF openDocument operation is scant and seldom helpful.
+ It's clear that their file access modes are inconsistently
+ implemented, and that at least:
+
+ r = either an FIFO or a real file, without truncation.
+ w = either an FIFO or a real file, with truncation.
+ wt = either an FIFO or a real file, with truncation.
+ rw = a real file, without truncation.
+ rwt = a real file, with truncation.
+
+ This diverges from the self-contradicting documentation, where
+ openDocument says nothing about truncation, and openFile, where
+ w can elect not to truncate.
+
+ Since Emacs is prepared to handle FIFOs within fileio.c, simply
+ use the straightforward relationships possible. */
method = service_class.open_document;
- trunc = (flags & O_TRUNC);
- write = (((flags & O_RDWR) == O_RDWR) || (flags & O_WRONLY));
+ read = trunc = write = false;
+
+ if ((flags & O_RDWR) == O_RDWR || (flags & O_WRONLY))
+ write = true;
+
+ if (flags & O_TRUNC)
+ trunc = true;
+
+ if ((flags & O_RDWR) == O_RDWR || !write)
+ read = true;
+
inside_saf_critical_section = true;
descriptor
= (*android_java_env)->CallNonvirtualObjectMethod (android_java_env,
emacs_service,
service_class.class,
method, uri, id,
- write, trunc);
+ read, write, trunc);
inside_saf_critical_section = false;
if (android_saf_exception_check (2, uri, id))
@@ -6448,6 +6482,8 @@ android_vfs_init (JNIEnv *env, jobject manager)
vnodes may not be reentrant, but operating on them from within an
async input handler will at worst cause an error to be returned.
+ The eight is that some vnode types do not support O_APPEND.
+
And the final drawback is that directories cannot be directly
opened. Instead, `dirfd' must be called on a directory stream used
by `openat'.