string; make it writable if WRITABLE, and readable if READABLE.
Truncate the file if TRUNCATE.
- Value is the resulting file descriptor or -1 upon failure. */
+ Value is the resulting file descriptor or an exception will be
+ raised. */
public int
- openContentUri (byte[] bytes, boolean writable, boolean readable,
+ openContentUri (String uri, boolean writable, boolean readable,
boolean truncate)
+ throws FileNotFoundException, IOException
{
String name, mode;
ParcelFileDescriptor fd;
if (truncate)
mode += "t";
- /* Try to open an associated ParcelFileDescriptor. */
+ /* Try to open a corresponding ParcelFileDescriptor. Though
+ `fd.detachFd' is exclusive to Honeycomb and up, this function is
+ never called on systems older than KitKat, which is Emacs's
+ minimum requirement for access to /content/by-authority. */
- try
- {
- /* The usual file name encoding question rears its ugly head
- again. */
-
- name = new String (bytes, "UTF-8");
- fd = resolver.openFileDescriptor (Uri.parse (name), mode);
-
- /* Use detachFd on newer versions of Android or plain old
- dup. */
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1)
- {
- i = fd.detachFd ();
- fd.close ();
-
- return i;
- }
- else
- {
- i = EmacsNative.dup (fd.getFd ());
- fd.close ();
+ fd = resolver.openFileDescriptor (Uri.parse (uri), mode);
+ i = fd.detachFd ();
+ fd.close ();
- return i;
- }
- }
- catch (Exception exception)
- {
- exception.printStackTrace ();
- return -1;
- }
+ return i;
}
/* Return whether Emacs is directly permitted to access the
FIND_METHOD (reset_ic, "resetIC",
"(Lorg/gnu/emacs/EmacsWindow;I)V");
FIND_METHOD (open_content_uri, "openContentUri",
- "([BZZZ)I");
+ "(Ljava/lang/String;ZZZ)I");
FIND_METHOD (check_content_uri, "checkContentUri",
"(Ljava/lang/String;ZZ)Z");
FIND_METHOD (query_battery, "queryBattery", "()[J");
return NULL;
}
- /* NAME must be a valid JNI string, so that it can be encoded
- properly. */
+ /* If the URI is not a valid JNI string, return immediately. This
+ should not be possible, since /content file names are encoded
+ into JNI strings at the naming stage; the check is performed
+ only out of an abundance of caution. */
if (android_verify_jni_string (name))
goto no_entry;
AAsset **asset)
{
struct android_authority_vnode *vp;
- size_t length;
jobject string;
int fd;
JNIEnv *env;
feasible. */
env = android_java_env;
- /* Allocate a buffer to hold the file name. */
- length = strlen (vp->uri);
- string = (*env)->NewByteArray (env, length);
- if (!string)
- {
- (*env)->ExceptionClear (env);
- errno = ENOMEM;
- return -1;
- }
-
- /* Copy the URI into this byte array. */
- (*env)->SetByteArrayRegion (env, string, 0, length,
- (jbyte *) vp->uri);
+ /* Allocate a JNI string to hold VP->uri. */
+ string = (*env)->NewStringUTF (env, vp->uri);
+ android_exception_check ();
/* Try to open the file descriptor. */
-
fd = (*env)->CallNonvirtualIntMethod (env, emacs_service,
service_class.class,
service_class.open_content_uri,
(jboolean) !(mode & O_WRONLY),
(jboolean) ((mode & O_TRUNC)
!= 0));
- if ((*env)->ExceptionCheck (env))
- {
- (*env)->ExceptionClear (env);
- errno = ENOMEM;
- ANDROID_DELETE_LOCAL_REF (string);
- return -1;
- }
+ android_exception_check_1 (string);
/* If fd is -1, just assume that the file does not exist,
and return -1 with errno set to ENOENT. */