root/src/androidvfs.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. android_init_cursor_class
  2. android_init_entry_class
  3. android_init_fd_class
  4. android_vfs_canonicalize_name
  5. android_unix_name
  6. android_unix_vnode
  7. android_unix_open
  8. android_unix_close
  9. android_unix_unlink
  10. android_unix_symlink
  11. android_unix_rmdir
  12. android_unix_rename
  13. android_unix_stat
  14. android_unix_access
  15. android_unix_mkdir
  16. android_unix_chmod
  17. android_unix_readlink
  18. android_unix_readdir
  19. android_unix_closedir
  20. android_unix_dirfd
  21. android_unix_opendir
  22. android_extract_long
  23. android_scan_directory_tree
  24. android_is_directory
  25. android_init_assets
  26. android_hack_asset_fd_fallback
  27. android_detect_ashmem
  28. android_hack_asset_fd
  29. android_afs_name
  30. android_afs_initial
  31. android_close_on_exec
  32. android_afs_open
  33. android_afs_close
  34. android_afs_unlink
  35. android_afs_symlink
  36. android_afs_rmdir
  37. android_afs_rename
  38. android_afs_stat
  39. android_afs_access
  40. android_afs_mkdir
  41. android_afs_chmod
  42. android_afs_readlink
  43. android_afs_readdir
  44. android_afs_closedir
  45. android_afs_dirfd
  46. android_afs_opendir
  47. android_afs_get_directory_name
  48. android_content_name
  49. android_content_open
  50. android_content_close
  51. android_content_unlink
  52. android_content_symlink
  53. android_content_rmdir
  54. android_content_rename
  55. android_content_stat
  56. android_content_access
  57. android_content_mkdir
  58. android_content_chmod
  59. android_content_readlink
  60. android_content_readdir
  61. android_content_closedir
  62. android_content_dirfd
  63. android_content_opendir
  64. android_content_get_directory_name
  65. android_content_initial
  66. android_get_content_name
  67. android_check_content_access
  68. android_authority_name
  69. android_authority_open
  70. android_authority_close
  71. android_authority_unlink
  72. android_authority_symlink
  73. android_authority_rmdir
  74. android_authority_rename
  75. android_authority_stat
  76. android_authority_access
  77. android_authority_mkdir
  78. android_authority_chmod
  79. android_authority_readlink
  80. android_authority_opendir
  81. android_authority_initial
  82. android_saf_valid_authority_p
  83. android_saf_root_name
  84. android_saf_root_open
  85. android_saf_root_close
  86. android_saf_root_unlink
  87. android_saf_root_symlink
  88. android_saf_root_rmdir
  89. android_saf_root_rename
  90. android_saf_root_stat
  91. android_saf_root_access
  92. android_saf_root_mkdir
  93. android_saf_root_chmod
  94. android_saf_root_readlink
  95. android_saf_root_readdir
  96. android_saf_root_closedir
  97. android_saf_root_dirfd
  98. android_saf_root_opendir
  99. android_saf_root_initial
  100. android_saf_root_get_directory
  101. android_saf_exception_check
  102. android_saf_stat
  103. android_saf_access
  104. android_saf_delete_document
  105. android_saf_rename_document
  106. android_saf_move_document
  107. android_document_id_from_name
  108. android_saf_tree_name
  109. android_saf_tree_open
  110. android_saf_tree_close
  111. android_saf_tree_unlink
  112. android_saf_tree_symlink
  113. android_saf_tree_rmdir
  114. android_saf_tree_rename
  115. android_saf_tree_stat
  116. android_saf_tree_access
  117. android_saf_tree_mkdir
  118. android_saf_tree_chmod
  119. android_saf_tree_readlink
  120. android_saf_tree_opendir_1
  121. android_saf_tree_readdir
  122. android_saf_tree_closedir
  123. android_saf_tree_dirfd
  124. android_saf_tree_opendir
  125. android_saf_tree_from_name
  126. android_saf_tree_get_directory
  127. android_saf_file_name
  128. android_saf_file_open
  129. android_saf_file_unlink
  130. android_saf_file_rmdir
  131. android_saf_file_opendir
  132. android_close_parcel_fd
  133. android_saf_new_name
  134. android_saf_new_open
  135. android_saf_new_unlink
  136. android_saf_new_symlink
  137. android_saf_new_rmdir
  138. android_saf_new_rename
  139. android_saf_new_stat
  140. android_saf_new_access
  141. android_saf_new_mkdir
  142. android_saf_new_chmod
  143. android_saf_new_readlink
  144. android_saf_new_opendir
  145. android_root_name
  146. android_name_file
  147. android_vfs_init
  148. android_open
  149. android_unlink
  150. android_symlink
  151. android_rmdir
  152. android_mkdir
  153. android_renameat_noreplace
  154. android_rename
  155. android_fstat
  156. android_fstatat_1
  157. android_fstatat
  158. android_faccessat
  159. android_fchmodat
  160. android_readlinkat
  161. android_fdopen
  162. android_close
  163. android_fclose
  164. android_open_asset
  165. android_close_asset
  166. android_asset_read_quit
  167. android_asset_read
  168. android_asset_lseek
  169. android_asset_fstat
  170. android_opendir
  171. android_dirfd
  172. android_readdir
  173. android_closedir

     1 /* Android virtual file-system support for GNU Emacs.
     2 
     3 Copyright (C) 2023 Free Software Foundation, Inc.
     4 
     5 This file is part of GNU Emacs.
     6 
     7 GNU Emacs is free software: you can redistribute it and/or modify
     8 it under the terms of the GNU General Public License as published by
     9 the Free Software Foundation, either version 3 of the License, or (at
    10 your option) any later version.
    11 
    12 GNU Emacs is distributed in the hope that it will be useful,
    13 but WITHOUT ANY WARRANTY; without even the implied warranty of
    14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    15 GNU General Public License for more details.
    16 
    17 You should have received a copy of the GNU General Public License
    18 along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
    19 
    20 #include <config.h>
    21 #include <fcntl.h>
    22 #include <unistd.h>
    23 #include <assert.h>
    24 #include <dlfcn.h>
    25 #include <dirent.h>
    26 #include <errno.h>
    27 #include <minmax.h>
    28 #include <string.h>
    29 #include <semaphore.h>
    30 
    31 #include <sys/stat.h>
    32 #include <sys/mman.h>
    33 
    34 #include <stat-time.h>
    35 
    36 #include <linux/ashmem.h>
    37 
    38 #include "android.h"
    39 #include "systime.h"
    40 #include "blockinput.h"
    41 
    42 #if __ANDROID_API__ >= 9
    43 #include <android/asset_manager.h>
    44 #include <android/asset_manager_jni.h>
    45 #else /* __ANDROID_API__ < 9 */
    46 #include "android-asset.h"
    47 #endif /* __ANDROID_API__ >= 9 */
    48 
    49 #include <android/log.h>
    50 
    51 /* This file implements support for the various special-purpose
    52    directories found on Android systems through a series of functions
    53    that substitute for Unix system call wrappers.  Such directories
    54    are not mounted in the Unix virtual file-system, but instead
    55    require the use of special system APIs to access; Emacs pretends
    56    they are mounted at specific folders within the root directory.
    57 
    58    There are presently two directories: /assets, granting access to
    59    asset files stored within the APK, and /content, providing direct
    60    access to content URIs (in Android 4.4 and later) and content
    61    directory trees (in Android 5.0 and later.)
    62 
    63    Substitutes for the C library `open', `fstat', `close', `fclose',
    64    `unlink', `symlink', `rmdir', `rename', `stat' system call wrappers
    65    are implemented, which delegate their actions to function tables
    66    contained inside ``VFS nodes''.
    67 
    68    The functions of a VFS node are to provide the implementations of
    69    the Unix file system operations that can be carried out on the file
    70    designated by its name and to connect useful information (such as
    71    internal file handles or identifiers) with those file names.  To
    72    those ends, there exist several different types of vnodes, each
    73    with a different set of functions and supplementary attributes.
    74 
    75    The key to locating the correct vnode for any given file name is an
    76    additional file system operation, defined by each node, which
    77    ``names'' children.  This operation takes a relative file name and
    78    returns a second node designating a constituent sub-file.
    79 
    80    When a file system function is called, it invokes the `name'
    81    operation of a special root vnode conceptually located at the top
    82    of the Unix file system hierarchy, handing it the complete file
    83    name given to it.  This vnode's name operation examines the first
    84    component of the relative file name it receives and creates either
    85    an asset, content, or Unix vnode, and calls the new vnode's `name'
    86    operation with the remainder of the file name.
    87 
    88    The vnode(s) created by each `name' operation may in turn create
    89    different vnodes based on the components of the names they have
    90    been provided that are used to repeat this process until no
    91    components remain.  The vnode created for the last component of the
    92    file name will provide its file system operations or be passed as
    93    an argument to other file system operations to which the file has
    94    been passed as an argument.
    95 
    96    The substitute functions defined have two caveats, which however
    97    don't prove problematic in an Emacs context: the first is that the
    98    treatment of `..' is inconsistent with Unix, and has not really
    99    been tested, while the second is that errno values do not always
   100    conform to what the corresponding Unix system calls may return.
   101    These caveats are described in more detail inside the last few
   102    pages of this file.  */
   103 
   104 /* Structure describing an array of VFS operations.  */
   105 
   106 struct android_vnode;
   107 
   108 struct android_vdir
   109 {
   110   /* Return a `struct dirent' describing the next file in this
   111      directory stream, or NULL if the stream has reached its end.  */
   112   struct dirent *(*readdir) (struct android_vdir *);
   113 
   114   /* Close and release all resources allocated for this directory
   115      stream.  */
   116   void (*closedir) (struct android_vdir *);
   117 
   118   /* Return a ``file descriptor'' tied to this directory stream.  */
   119   int (*dirfd) (struct android_vdir *);
   120 };
   121 
   122 struct android_vops
   123 {
   124   /* Name a child of the given VFS node, which should be a
   125      directory.
   126 
   127      LENGTH should be the length of NAME, excluding that of any
   128      trailing NULL byte.
   129 
   130      NAME should be a normalized and NULL-terminated relative file
   131      name; it may contain a leading separator characters, but no
   132      consecutive ones.
   133 
   134      If NAME is empty, create another VFS node designating the same
   135      file instead.
   136 
   137      NAME should also be located within writable storage; it may be
   138      overwritten as the vnode sees fit.
   139 
   140      Value is a VFS node corresponding to the child, or NULL upon
   141      failure.
   142 
   143      A VFS node may be returned even if NAME does not exist, the
   144      expectation being that either a later filesystem operation will
   145      fail, or will create the file.  */
   146   struct android_vnode *(*name) (struct android_vnode *, char *, size_t);
   147 
   148   /* Open the specified VNODE, returning either a file descriptor or
   149      an asset file descriptor.
   150 
   151      FLAGS and MODE mean the same as they do to the Unix `open' system
   152      call.
   153 
   154      ASSET_P stipulates if an asset file descriptor may be returned;
   155      if true, *ASSET may be set to an asset file descriptor.
   156 
   157      If an asset file descriptor is unavailable or ASSET_P is false,
   158      *FD will be set to a file descriptor.
   159 
   160      If the vnode cannot be opened, value is -1 with errno set
   161      accordingly.  Otherwise, value is 0 if a file descriptor was
   162      returned, and 1 if an asset file descriptor was returned.  */
   163   int (*open) (struct android_vnode *, int, mode_t, bool,
   164                int *, AAsset **);
   165 
   166   /* Close the specified VNODE, releasing all of its resources.
   167      Save errno before making system calls that may set it, and
   168      restore it to its original value before returning.
   169 
   170      This is unrelated to `android_close', which primarily releases on
   171      stat buffers linked to file or asset file descriptors.  */
   172   void (*close) (struct android_vnode *);
   173 
   174   /* Unlink the file and the specified VNODE.  Value and errno are the
   175      same as Unix `unlink'.  */
   176   int (*unlink) (struct android_vnode *);
   177 
   178   /* Create a symlink from the specified VNODE to the target TARGET.
   179      Value and errno are the same as `symlink' on Linux (which notably
   180      means that errno is set to EPERM if VNODE doesn't support
   181      symlinks.)  */
   182   int (*symlink) (const char *, struct android_vnode *);
   183 
   184   /* Remove VNODE from its parent directory.  VNODE must be an empty
   185      directory.  Value and errno are the same as Unix `rmdir'.  */
   186   int (*rmdir) (struct android_vnode *);
   187 
   188   /* Move the file designated by SRC to DST, overwriting DST if
   189      KEEP_EXISTING is false.
   190 
   191      If KEEP_EXISTING is true and DST already exists, value is -1 with
   192      errno set to EEXIST.
   193 
   194      If VNODE does not natively support checking for a preexisting DST
   195      and KEEP_EXISTING is true, value is -1 with errno set to ENOSYS.
   196 
   197      Value is otherwise the same as `rename'.  */
   198   int (*rename) (struct android_vnode *, struct android_vnode *, bool);
   199 
   200   /* Return statistics for the specified VNODE.
   201      Value and errno are the same as with Unix `stat'.  */
   202   int (*stat) (struct android_vnode *, struct stat *);
   203 
   204   /* Return whether or not VNODE is accessible.
   205      Value, errno and MODE are the same as with Unix `access'.  */
   206   int (*access) (struct android_vnode *, int);
   207 
   208   /* Make a directory designated by VNODE, like Unix `mkdir'.  */
   209   int (*mkdir) (struct android_vnode *, mode_t);
   210 
   211   /* Change the access mode of the provided VNODE to MODE.  Value is
   212      the same as with `chmod'.  FLAGS is passed verbatim from the call
   213      to the delegating at-func, and is probably
   214      AT_SYMLINK_NOFOLLOW.  */
   215   int (*chmod) (struct android_vnode *, mode_t, int);
   216 
   217   /* Return the target of VNODE if it is a symbolic link, or -1.
   218      Value and errno are the same as with `readlink'.  */
   219   ssize_t (*readlink) (struct android_vnode *, char *, size_t);
   220 
   221   /* Open the specified VNODE as a directory.
   222      Value is a ``directory handle'', or NULL upon failure.  */
   223   struct android_vdir *(*opendir) (struct android_vnode *);
   224 };
   225 
   226 struct android_vnode
   227 {
   228   /* Operations associated with this vnode.  */
   229   struct android_vops *ops;
   230 
   231   /* Type of this vnode and its flags.  */
   232   short type, flags;
   233 };
   234 
   235 /* Structure describing a special named vnode relative to the root
   236    vnode, or another directory vnode.  */
   237 
   238 struct android_special_vnode
   239 {
   240   /* The name of the special file.  */
   241   const char *name;
   242 
   243   /* The length of that name.  */
   244   size_t length;
   245 
   246   /* Function called to create the initial vnode from the rest of the
   247      component.  */
   248   struct android_vnode *(*initial) (char *, size_t);
   249 };
   250 
   251 enum android_vnode_type
   252   {
   253     ANDROID_VNODE_UNIX,
   254     ANDROID_VNODE_AFS,
   255     ANDROID_VNODE_CONTENT,
   256     ANDROID_VNODE_CONTENT_AUTHORITY,
   257     ANDROID_VNODE_SAF_ROOT,
   258     ANDROID_VNODE_SAF_TREE,
   259     ANDROID_VNODE_SAF_FILE,
   260     ANDROID_VNODE_SAF_NEW,
   261   };
   262 
   263 
   264 
   265 /* Structure describing the android.database.Cursor class.  */
   266 
   267 struct android_cursor_class
   268 {
   269   jclass class;
   270   jmethodID close;
   271 };
   272 
   273 /* Structure describing the EmacsDirectoryEntry class.  */
   274 
   275 struct emacs_directory_entry_class
   276 {
   277   jclass class;
   278   jfieldID d_type;
   279   jfieldID d_name;
   280 };
   281 
   282 /* Structure describing the android.os.ParcelFileDescriptor class used
   283    to wrap file descriptors sent over IPC.  */
   284 
   285 struct android_parcel_file_descriptor_class
   286 {
   287   jclass class;
   288   jmethodID close;
   289   jmethodID get_fd;
   290   jmethodID detach_fd;
   291 };
   292 
   293 /* The java.lang.String class.  */
   294 static jclass java_string_class;
   295 
   296 /* Fields and methods associated with the Cursor class.  */
   297 static struct android_cursor_class cursor_class;
   298 
   299 /* Fields and methods associated with the EmacsDirectoryEntry
   300    class.  */
   301 static struct emacs_directory_entry_class entry_class;
   302 
   303 /* Fields and methods associated with the ParcelFileDescriptor
   304    class.  */
   305 static struct android_parcel_file_descriptor_class fd_class;
   306 
   307 /* Global references to several exception classes.  */
   308 static jclass file_not_found_exception, security_exception;
   309 static jclass operation_canceled_exception;
   310 static jclass unsupported_operation_exception, out_of_memory_error;
   311 
   312 /* Initialize `cursor_class' using the given JNI environment ENV.
   313    Calling this function is not necessary on Android 4.4 and
   314    earlier.  */
   315 
   316 static void
   317 android_init_cursor_class (JNIEnv *env)
   318 {
   319   jclass old;
   320 
   321   cursor_class.class
   322     = (*env)->FindClass (env, "android/database/Cursor");
   323   eassert (cursor_class.class);
   324 
   325   old = cursor_class.class;
   326   cursor_class.class
   327     = (jclass) (*env)->NewGlobalRef (env, (jobject) old);
   328   (*env)->DeleteLocalRef (env, old);
   329 
   330   if (!cursor_class.class)
   331     emacs_abort ();
   332 
   333 #define FIND_METHOD(c_name, name, signature)            \
   334   cursor_class.c_name                                   \
   335     = (*env)->GetMethodID (env, cursor_class.class,     \
   336                            name, signature);            \
   337   assert (cursor_class.c_name);
   338   FIND_METHOD (close, "close", "()V");
   339 #undef FIND_METHOD
   340 }
   341 
   342 /* Initialize `entry_class' using the given JNI environment ENV.
   343    Calling this function is not necessary on Android 4.4 and
   344    earlier.  */
   345 
   346 static void
   347 android_init_entry_class (JNIEnv *env)
   348 {
   349   jclass old;
   350 
   351   entry_class.class
   352     = (*env)->FindClass (env, "org/gnu/emacs/EmacsDirectoryEntry");
   353   eassert (entry_class.class);
   354 
   355   old = entry_class.class;
   356   entry_class.class
   357     = (jclass) (*env)->NewGlobalRef (env, (jobject) old);
   358   (*env)->DeleteLocalRef (env, old);
   359 
   360   if (!entry_class.class)
   361     emacs_abort ();
   362 
   363   entry_class.d_type = (*env)->GetFieldID (env, entry_class.class,
   364                                            "d_type", "I");
   365   entry_class.d_name = (*env)->GetFieldID (env, entry_class.class,
   366                                            "d_name",
   367                                            "Ljava/lang/String;");
   368   assert (entry_class.d_type && entry_class.d_name);
   369 }
   370 
   371 
   372 /* Initialize `fd_class' using the given JNI environment ENV.  Calling
   373    this function is not necessary on Android 4.4 and earlier.  */
   374 
   375 static void
   376 android_init_fd_class (JNIEnv *env)
   377 {
   378   jclass old;
   379 
   380   fd_class.class
   381     = (*env)->FindClass (env, "android/os/ParcelFileDescriptor");
   382   eassert (fd_class.class);
   383 
   384   old = fd_class.class;
   385   fd_class.class
   386     = (jclass) (*env)->NewGlobalRef (env, (jobject) old);
   387   (*env)->DeleteLocalRef (env, old);
   388 
   389   if (!fd_class.class)
   390     emacs_abort ();
   391 
   392 #define FIND_METHOD(c_name, name, signature)            \
   393   fd_class.c_name                                       \
   394     = (*env)->GetMethodID (env, fd_class.class,         \
   395                            name, signature);            \
   396   assert (fd_class.c_name);
   397   FIND_METHOD (close, "close", "()V");
   398   FIND_METHOD (get_fd, "getFd", "()I");
   399   FIND_METHOD (detach_fd, "detachFd", "()I");
   400 #undef FIND_METHOD
   401 }
   402 
   403 
   404 
   405 /* Delete redundant instances of `.' and `..' from NAME in-place.
   406    NAME must be *LENGTH long, excluding a mandatory trailing NULL
   407    byte.
   408 
   409    Transform each directory component in NAME to avoid instances
   410    of the `.' and `..' directories.  For example, turn:
   411 
   412      a/../b/c/.
   413 
   414    into
   415 
   416      b/c/
   417 
   418    and return NULL, writing the new length of NAME into *LENGTH.
   419 
   420    If there are more `..' components in NAME than there are normal
   421    file name components, return NAME incremented to the position after
   422    the first `..' component that cannot be transformed.  For example,
   423    if NAME is
   424 
   425      a/../../a
   426 
   427    value will be
   428 
   429      a
   430 
   431    If NAME is a directory separator and LENGTH is 1, return without
   432    modifying NAME.  In any other case, omit any leading directory
   433    separator when writing to NAME.  This is useful when a vnode that
   434    can only be opened as a directory is desired, as this status is
   435    made clear by suffixing the file name with a trailing
   436    directory separator.  */
   437 
   438 static char *
   439 android_vfs_canonicalize_name (char *name, size_t *length)
   440 {
   441   size_t nellipsis, i;
   442   char *last_component, *prev_component, *fill, *orig_name;
   443   size_t size;
   444 
   445   /* Special case described in the last paragraph of the comment
   446      above.  */
   447 
   448   size = *length;
   449   orig_name = name;
   450 
   451   if (*name == '/' && size == 1)
   452     return NULL;
   453   else if (*name == '/')
   454     size -= 1;
   455 
   456   nellipsis = 0; /* Number of ellipsis encountered within the current
   457                     file name component, or -1.  */
   458   prev_component = NULL; /* Pointer to the separator character of
   459                             the component immediately before the
   460                             component currently being written.  */
   461   last_component = name; /* Pointer to the separator character of
   462                             the component currently being read.  */
   463   fill = name; /* Pointer to the next character that will be written
   464                   within NAME.  */
   465 
   466   /* Adjust name to skip the leading directory separator.  But only
   467      after fill is set.  */
   468   if (*name == '/')
   469     name++;
   470 
   471   for (i = 0; i < size; ++i)
   472     {
   473       switch (name[i])
   474         {
   475         case '/':
   476           /* See if the previous component was `..' or `.'.
   477 
   478              If it is .., and if no previous directory separator was
   479              encountered, return or look up a vnode representing the
   480              parent.  */
   481 
   482           if (nellipsis == 2)
   483             {
   484               /* .. */
   485 
   486               if (!prev_component)
   487                 goto parent_vnode;
   488 
   489               /* Return to the last component.  */
   490               fill = prev_component;
   491 
   492               /* Restore last_component to prev_component, and
   493                  prev_component back to the component before that.  */
   494               last_component = prev_component;
   495 
   496               if (last_component != name)
   497                 prev_component = memrchr (name, '/',
   498                                           last_component - name - 1);
   499               else
   500                 prev_component = NULL;
   501 
   502               /* prev_component may now be NULL.  If last_component is
   503                  the same as NAME, then fill has really been returned
   504                  to the beginning of the string, so leave it be.  But
   505                  if it's something else, then it must be the first
   506                  separator character in the string, so set
   507                  prev_component to NAME itself.  */
   508 
   509               if (!prev_component && last_component != name)
   510                 prev_component = name;
   511             }
   512           else if (nellipsis == 1)
   513             /* If it's ., return to this component.  */
   514             fill = last_component;
   515           else
   516             {
   517               /* Record the position of the last directory separator,
   518                  so NAME can be overwritten from there onwards if `..'
   519                  or `.' are encountered.  */
   520               prev_component = last_component;
   521               last_component = fill;
   522             }
   523 
   524           /* Allow tracking ellipses again.  */
   525           nellipsis = 0;
   526           break;
   527 
   528         case '.':
   529           if (nellipsis != -1)
   530             nellipsis++;
   531           break;
   532 
   533         default:
   534           nellipsis = -1;
   535           break;
   536         }
   537 
   538       /* Now copy this character over from NAME.  */
   539       *fill++ = name[i];
   540     }
   541 
   542   /* See if the previous component was `..' or `.'.
   543 
   544      If it is .., and if no previous directory separator was
   545      encountered, return or look up a vnode representing the
   546      parent.  */
   547 
   548   if (nellipsis == 2)
   549     {
   550       /* .. */
   551 
   552       if (!prev_component)
   553         /* Look up the rest of the vnode in its parent.  */
   554         goto parent_vnode;
   555 
   556       /* Return to the last component.  */
   557       fill = prev_component;
   558       nellipsis = -2;
   559     }
   560   else if (nellipsis == 1)
   561     {
   562       /* If it's ., return to this component.  */
   563       fill = last_component;
   564       nellipsis = -2;
   565     }
   566 
   567   /* Now, if there's enough room and an ellipsis file name was the
   568      last component of END, append a trailing `/' before NULL
   569      terminating it, indicating that the file name must be a
   570      directory.  */
   571 
   572   if (fill + 1 < name + size && nellipsis == -2)
   573     *fill++ = '/';
   574 
   575   /* NULL terminate fill.  */
   576   *fill = '\0';
   577   *length = fill - orig_name;
   578   return NULL;
   579 
   580  parent_vnode:
   581   /* .. was encountered and the parent couldn't be found through
   582      stripping off preceding components.
   583 
   584      Find the parent vnode and name the rest of NAME starting from
   585      there.  */
   586   return name + i;
   587 }
   588 
   589 
   590 
   591 /* Unix vnode implementation.  These VFS nodes directly wrap around
   592    the Unix filesystem, with the exception of the root vnode.  */
   593 
   594 struct android_unix_vnode
   595 {
   596   /* The vnode data itself.  */
   597   struct android_vnode vnode;
   598 
   599   /* Length of the name without a trailing null byte.  */
   600   size_t name_length;
   601 
   602   /* Name of the vnode.  */
   603   char *name;
   604 };
   605 
   606 struct android_unix_vdir
   607 {
   608   /* The directory function table.  */
   609   struct android_vdir vdir;
   610 
   611   /* The directory stream.  */
   612   DIR *directory;
   613 };
   614 
   615 /* The vnode representing the root filesystem.  */
   616 static struct android_unix_vnode root_vnode;
   617 
   618 static struct android_vnode *android_unix_name (struct android_vnode *,
   619                                                 char *, size_t);
   620 static int android_unix_open (struct android_vnode *, int,
   621                               mode_t, bool, int *, AAsset **);
   622 static void android_unix_close (struct android_vnode *);
   623 static int android_unix_unlink (struct android_vnode *);
   624 static int android_unix_symlink (const char *, struct android_vnode *);
   625 static int android_unix_rmdir (struct android_vnode *);
   626 static int android_unix_rename (struct android_vnode *,
   627                                 struct android_vnode *, bool);
   628 static int android_unix_stat (struct android_vnode *, struct stat *);
   629 static int android_unix_access (struct android_vnode *, int);
   630 static int android_unix_mkdir (struct android_vnode *, mode_t);
   631 static int android_unix_chmod (struct android_vnode *, mode_t, int);
   632 static ssize_t android_unix_readlink (struct android_vnode *, char *,
   633                                       size_t);
   634 static struct android_vdir *android_unix_opendir (struct android_vnode *);
   635 
   636 /* Vector of VFS operations associated with Unix filesystem VFS
   637    nodes.  */
   638 
   639 static struct android_vops unix_vfs_ops =
   640   {
   641     android_unix_name,
   642     android_unix_open,
   643     android_unix_close,
   644     android_unix_unlink,
   645     android_unix_symlink,
   646     android_unix_rmdir,
   647     android_unix_rename,
   648     android_unix_stat,
   649     android_unix_access,
   650     android_unix_mkdir,
   651     android_unix_chmod,
   652     android_unix_readlink,
   653     android_unix_opendir,
   654   };
   655 
   656 static struct android_vnode *
   657 android_unix_name (struct android_vnode *vnode, char *name,
   658                    size_t length)
   659 {
   660   struct android_unix_vnode *vp, *input, temp;
   661   char *fill, *remainder;
   662   size_t j;
   663 
   664   /* Canonicalize NAME.  */
   665   input = (struct android_unix_vnode *) vnode;
   666   remainder = android_vfs_canonicalize_name (name, &length);
   667 
   668   /* If remainder is set, it's a name relative to the parent
   669      vnode.  */
   670   if (remainder)
   671     goto parent_vnode;
   672 
   673   /* Create a new unix vnode.  */
   674   vp = xmalloc (sizeof *vp);
   675 
   676   /* If name is empty, duplicate the current vnode.  */
   677 
   678   if (length < 1)
   679     {
   680       memcpy (vp, vnode, sizeof *vp);
   681       vp->name = xstrdup (vp->name);
   682       return &vp->vnode;
   683     }
   684 
   685   /* Otherwise, fill in the vnode.  */
   686 
   687   vp->vnode.ops = &unix_vfs_ops;
   688   vp->vnode.type = ANDROID_VNODE_UNIX;
   689   vp->vnode.flags = 0;
   690 
   691   /* Generate the new name of the vnode.  Remove any trailing slash
   692      from vp->name.  */
   693 
   694   vp->name_length = input->name_length + length;
   695   vp->name = xmalloc (vp->name_length + 2);
   696 
   697   /* Copy the parent name over.  */
   698   fill = mempcpy (vp->name, input->name, input->name_length);
   699 
   700   /* Check if it contains a trailing slash.  input->name cannot be
   701      empty, as the root vnode's name is `/'.  */
   702 
   703   if (fill[-1] != '/' && *name != '/')
   704     /* If not, append a trailing slash and adjust vp->name_length
   705        correspondingly.  */
   706     *fill++ = '/', vp->name_length++;
   707   else if (fill[-1] == '/' && *name == '/')
   708     /* If name has a leading slash and fill does too, move fill
   709        backwards so that name's slash will override that of fill.  */
   710     fill--, vp->name_length--;
   711 
   712   /* Now copy NAME.  */
   713   fill = mempcpy (fill, name, length);
   714 
   715   /* And NULL terminate fill.  */
   716   *fill = '\0';
   717   return &vp->vnode;
   718 
   719  parent_vnode:
   720   /* .. was encountered and the parent couldn't be found through
   721      stripping off preceding components.
   722 
   723      Find the parent vnode and name the rest of NAME starting from
   724      there.  */
   725 
   726   if (input->name_length == 1)
   727     /* This is the vnode representing the root directory; just look
   728        within itself... */
   729     vnode = &root_vnode.vnode;
   730   else
   731     {
   732       /* Create a temporary asset vnode within the parent and use it
   733          instead.  First, establish the length of vp->name before its
   734          last component.  */
   735 
   736       for (j = input->name_length - 1; j; --j)
   737         {
   738           if (input->name[j - 1] == '/')
   739             break;
   740         }
   741 
   742       /* There must be at least one leading directory separator in an
   743          asset vnode's `name' field.  */
   744 
   745       if (!j)
   746         abort ();
   747 
   748       /* j is now the length of the string minus the size of its last
   749          component.  Create a temporary vnode with that as its
   750          name.  */
   751 
   752       temp.vnode.ops = &unix_vfs_ops;
   753       temp.vnode.type = ANDROID_VNODE_UNIX;
   754       temp.vnode.flags = 0;
   755       temp.name_length = j;
   756       temp.name = xmalloc (j + 1);
   757       fill = mempcpy (temp.name, input->name, j);
   758       *fill = '\0';
   759 
   760       /* Search for the remainder of NAME relative to its parent.  */
   761       vnode = android_unix_name (&temp.vnode, remainder,
   762                                  strlen (remainder));
   763       xfree (temp.name);
   764       return vnode;
   765     }
   766 
   767   return (*vnode->ops->name) (vnode, remainder, strlen (remainder));
   768 }
   769 
   770 /* Create a Unix vnode representing the given file NAME.  Use this
   771    function to create vnodes that aren't rooted in the root VFS
   772    node.  */
   773 
   774 static struct android_vnode *
   775 android_unix_vnode (const char *name)
   776 {
   777   struct android_unix_vnode *vp;
   778 
   779   vp = xmalloc (sizeof *vp);
   780   vp->vnode.ops = &unix_vfs_ops;
   781   vp->vnode.type = ANDROID_VNODE_UNIX;
   782   vp->vnode.flags = 0;
   783   vp->name_length = strlen (name);
   784   vp->name = xstrdup (name);
   785   return &vp->vnode;
   786 }
   787 
   788 static int
   789 android_unix_open (struct android_vnode *vnode, int flags,
   790                    mode_t mode, bool asset_p, int *fd,
   791                    AAsset **asset)
   792 {
   793   struct android_unix_vnode *vp;
   794   int fds;
   795 
   796   vp = (struct android_unix_vnode *) vnode;
   797   fds = open (vp->name, flags, mode);
   798 
   799   if (fds < 0)
   800     return -1;
   801 
   802   *fd = fds;
   803   return 0;
   804 }
   805 
   806 static void
   807 android_unix_close (struct android_vnode *vnode)
   808 {
   809   struct android_unix_vnode *vp;
   810   int save_errno;
   811 
   812   save_errno = errno;
   813   vp = (struct android_unix_vnode *) vnode;
   814   xfree (vp->name);
   815   xfree (vp);
   816   errno = save_errno;
   817 }
   818 
   819 static int
   820 android_unix_unlink (struct android_vnode *vnode)
   821 {
   822   struct android_unix_vnode *vp;
   823 
   824   vp = (struct android_unix_vnode *) vnode;
   825   return unlink (vp->name);
   826 }
   827 
   828 static int
   829 android_unix_symlink (const char *target, struct android_vnode *vnode)
   830 {
   831   struct android_unix_vnode *vp;
   832 
   833   vp = (struct android_unix_vnode *) vnode;
   834   return symlink (target, vp->name);
   835 }
   836 
   837 static int
   838 android_unix_rmdir (struct android_vnode *vnode)
   839 {
   840   struct android_unix_vnode *vp;
   841 
   842   vp = (struct android_unix_vnode *) vnode;
   843   return rmdir (vp->name);
   844 }
   845 
   846 static int
   847 android_unix_rename (struct android_vnode *src,
   848                      struct android_vnode *dst,
   849                      bool keep_existing)
   850 {
   851   struct android_unix_vnode *vp, *dest;
   852 
   853   if (src->type != dst->type)
   854     {
   855       /* If the types of both vnodes differ, complain that they're on
   856          two different filesystems (which is correct from a abstract
   857          viewpoint.)  */
   858       errno = EXDEV;
   859       return -1;
   860     }
   861 
   862   vp = (struct android_unix_vnode *) src;
   863   dest = (struct android_unix_vnode *) dst;
   864 
   865   return (keep_existing
   866           ? renameat_noreplace (AT_FDCWD, vp->name,
   867                                 AT_FDCWD, dest->name)
   868           : rename (vp->name, dest->name));
   869 }
   870 
   871 static int
   872 android_unix_stat (struct android_vnode *vnode, struct stat *statb)
   873 {
   874   struct android_unix_vnode *vp;
   875 
   876   vp = (struct android_unix_vnode *) vnode;
   877   return stat (vp->name, statb);
   878 }
   879 
   880 static int
   881 android_unix_access (struct android_vnode *vnode, int mode)
   882 {
   883   struct android_unix_vnode *vp;
   884 
   885   vp = (struct android_unix_vnode *) vnode;
   886   return access (vp->name, mode);
   887 }
   888 
   889 static int
   890 android_unix_mkdir (struct android_vnode *vnode, mode_t mode)
   891 {
   892   struct android_unix_vnode *vp;
   893 
   894   vp = (struct android_unix_vnode *) vnode;
   895   return mkdir (vp->name, mode);
   896 }
   897 
   898 static int
   899 android_unix_chmod (struct android_vnode *vnode, mode_t mode,
   900                     int flags)
   901 {
   902   struct android_unix_vnode *vp;
   903 
   904   vp = (struct android_unix_vnode *) vnode;
   905   return fchmodat (AT_FDCWD, vp->name, mode, flags);
   906 }
   907 
   908 static ssize_t
   909 android_unix_readlink (struct android_vnode *vnode, char *buffer,
   910                        size_t size)
   911 {
   912   struct android_unix_vnode *vp;
   913 
   914   vp = (struct android_unix_vnode *) vnode;
   915   return readlink (vp->name, buffer, size);
   916 }
   917 
   918 static struct dirent *
   919 android_unix_readdir (struct android_vdir *vdir)
   920 {
   921   struct android_unix_vdir *dir;
   922 
   923   dir = (struct android_unix_vdir *) vdir;
   924   return readdir (dir->directory);
   925 }
   926 
   927 static void
   928 android_unix_closedir (struct android_vdir *vdir)
   929 {
   930   struct android_unix_vdir *dir;
   931 
   932   dir = (struct android_unix_vdir *) vdir;
   933   closedir (dir->directory);
   934   xfree (vdir);
   935 }
   936 
   937 static int
   938 android_unix_dirfd (struct android_vdir *vdir)
   939 {
   940   struct android_unix_vdir *dir;
   941 
   942   dir = (struct android_unix_vdir *) vdir;
   943   return dirfd (dir->directory);
   944 }
   945 
   946 static struct android_vdir *
   947 android_unix_opendir (struct android_vnode *vnode)
   948 {
   949   struct android_unix_vnode *vp;
   950   struct android_unix_vdir *dir;
   951   DIR *directory;
   952 
   953   /* Try to opendir the vnode.  */
   954   vp = (struct android_unix_vnode *) vnode;
   955   directory = opendir (vp->name);
   956 
   957   if (!directory)
   958     return NULL;
   959 
   960   dir = xmalloc (sizeof *dir);
   961   dir->vdir.readdir = android_unix_readdir;
   962   dir->vdir.closedir = android_unix_closedir;
   963   dir->vdir.dirfd = android_unix_dirfd;
   964   dir->directory = directory;
   965   return &dir->vdir;
   966 }
   967 
   968 
   969 
   970 /* Asset directory handling functions.  ``directory-tree'' is a file in
   971    the root of the assets directory describing its contents.
   972 
   973    See lib-src/asset-directory-tool for more details.  */
   974 
   975 /* The Android directory tree.  */
   976 static const char *directory_tree;
   977 
   978 /* The size of the directory tree.  */
   979 static size_t directory_tree_size;
   980 
   981 /* The asset manager being used.  */
   982 static AAssetManager *asset_manager;
   983 
   984 /* Read an unaligned (32-bit) long from the address POINTER.  */
   985 
   986 static unsigned int
   987 android_extract_long (char *pointer)
   988 {
   989   unsigned int number;
   990 
   991   memcpy (&number, pointer, sizeof number);
   992   return number;
   993 }
   994 
   995 /* Scan to the file FILE in the asset directory tree.  Return a
   996    pointer to the end of that file (immediately before any children)
   997    in the directory tree, or NULL if that file does not exist.
   998 
   999    If returning non-NULL, also return the offset to the end of the
  1000    last subdirectory or file in *LIMIT_RETURN.  LIMIT_RETURN may be
  1001    NULL.
  1002 
  1003    FILE must have less than 11 levels of nesting.  If it ends with a
  1004    trailing slash, then NULL will be returned if it is not actually a
  1005    directory.  */
  1006 
  1007 static const char *
  1008 android_scan_directory_tree (char *file, size_t *limit_return)
  1009 {
  1010   char *token, *saveptr, *copy, *copy1, *start, *max, *limit;
  1011   size_t token_length, ntokens, i;
  1012   char *tokens[10];
  1013 
  1014   USE_SAFE_ALLOCA;
  1015 
  1016   /* Skip past the 5 byte header.  */
  1017   start = (char *) directory_tree + 5;
  1018 
  1019   /* Figure out the current limit.  */
  1020   limit = (char *) directory_tree + directory_tree_size;
  1021 
  1022   /* Now, split `file' into tokens, with the delimiter being the file
  1023      name separator.  Look for the file and seek past it.  */
  1024 
  1025   ntokens = 0;
  1026   saveptr = NULL;
  1027   copy = copy1 = xstrdup (file);
  1028   memset (tokens, 0, sizeof tokens);
  1029 
  1030   while ((token = strtok_r (copy, "/", &saveptr)))
  1031     {
  1032       copy = NULL;
  1033 
  1034       /* Make sure ntokens is within bounds.  */
  1035       if (ntokens == ARRAYELTS (tokens))
  1036         {
  1037           xfree (copy1);
  1038           goto fail;
  1039         }
  1040 
  1041       tokens[ntokens] = SAFE_ALLOCA (strlen (token) + 1);
  1042       memcpy (tokens[ntokens], token, strlen (token) + 1);
  1043       ntokens++;
  1044     }
  1045 
  1046   /* Free the copy created for strtok_r.  */
  1047   xfree (copy1);
  1048 
  1049   /* If there are no tokens, just return the start of the directory
  1050      tree.  */
  1051 
  1052   if (!ntokens)
  1053     {
  1054       SAFE_FREE ();
  1055 
  1056       /* Return the size of the directory tree as the limit.
  1057          Do not subtract the initial header bytes, as the limit
  1058          is an offset from the start of the file.  */
  1059 
  1060       if (limit_return)
  1061         *limit_return = directory_tree_size;
  1062 
  1063       return start;
  1064     }
  1065 
  1066   /* Loop through tokens, indexing the directory tree each time.  */
  1067 
  1068   for (i = 0; i < ntokens; ++i)
  1069     {
  1070       token = tokens[i];
  1071 
  1072       /* Figure out how many bytes to compare.  */
  1073       token_length = strlen (token);
  1074 
  1075     again:
  1076 
  1077       /* If this would be past the directory, return NULL.  */
  1078       if (start + token_length > limit)
  1079         goto fail;
  1080 
  1081       /* Now compare the file name.  */
  1082       if (!memcmp (start, token, token_length))
  1083         {
  1084           /* They probably match.  Find the NULL byte.  It must be
  1085              either one byte past start + token_length, with the last
  1086              byte a trailing slash (indicating that it is a
  1087              directory), or just start + token_length.  Return 4 bytes
  1088              past the next NULL byte.  */
  1089 
  1090           max = memchr (start, 0, limit - start);
  1091 
  1092           if (max != start + token_length
  1093               && !(max == start + token_length + 1
  1094                    && *(max - 1) == '/'))
  1095             goto false_positive;
  1096 
  1097           /* Return it if it exists and is in range, and this is the
  1098              last token.  Otherwise, set it as start and the limit as
  1099              start + the offset and continue the loop.  */
  1100 
  1101           if (max && max + 5 <= limit)
  1102             {
  1103               if (i < ntokens - 1)
  1104                 {
  1105                   start = max + 5;
  1106                   limit = ((char *) directory_tree
  1107                            + android_extract_long (max + 1));
  1108 
  1109                   /* Make sure limit is still in range.  */
  1110                   if (limit > directory_tree + directory_tree_size
  1111                       || start > directory_tree + directory_tree_size)
  1112                     goto fail;
  1113 
  1114                   continue;
  1115                 }
  1116 
  1117               /* Now see if max is not a directory and file is.  If
  1118                  file is a directory, then return NULL.  */
  1119               if (*(max - 1) != '/' && file[strlen (file) - 1] == '/')
  1120                 max = NULL;
  1121               else
  1122                 {
  1123                   /* Figure out the limit.  */
  1124                   if (limit_return)
  1125                     *limit_return = android_extract_long (max + 1);
  1126 
  1127                   /* Go to the end of this file.  */
  1128                   max += 5;
  1129                 }
  1130 
  1131               SAFE_FREE ();
  1132               return max;
  1133             }
  1134 
  1135           /* Return NULL otherwise.  */
  1136           __android_log_print (ANDROID_LOG_WARN, __func__,
  1137                                "could not scan to end of directory tree"
  1138                                ": %s", file);
  1139           goto fail;
  1140         }
  1141 
  1142     false_positive:
  1143 
  1144       /* No match was found.  Set start to the next sibling and try
  1145          again.  */
  1146 
  1147       start = memchr (start, 0, limit - start);
  1148 
  1149       if (!start || start + 5 > limit)
  1150         goto fail;
  1151 
  1152       start = ((char *) directory_tree
  1153                + android_extract_long (start + 1));
  1154 
  1155       /* Make sure start is still in bounds.  */
  1156 
  1157       if (start > limit)
  1158         goto fail;
  1159 
  1160       /* Continue the loop.  */
  1161       goto again;
  1162     }
  1163 
  1164  fail:
  1165   SAFE_FREE ();
  1166   return NULL;
  1167 }
  1168 
  1169 /* Return whether or not the directory tree entry DIR is a
  1170    directory.
  1171 
  1172    DIR should be a value returned by
  1173    `android_scan_directory_tree'.  */
  1174 
  1175 static bool
  1176 android_is_directory (const char *dir)
  1177 {
  1178   /* If the directory is the directory tree, then it is a
  1179      directory.  */
  1180   if (dir == directory_tree + 5)
  1181     return true;
  1182 
  1183   /* Otherwise, look 5 bytes behind.  If it is `/', then it is a
  1184      directory.  */
  1185   return (dir - 6 >= directory_tree
  1186           && *(dir - 6) == '/');
  1187 }
  1188 
  1189 /* Initialize asset retrieval.  ENV should be a JNI environment for
  1190    the Emacs thread, and MANAGER should be a local reference to a Java
  1191    asset manager object created for the Emacs service context.  */
  1192 
  1193 static void
  1194 android_init_assets (JNIEnv *env, jobject manager)
  1195 {
  1196   AAsset *asset;
  1197 
  1198   /* Set the asset manager.  */
  1199   asset_manager = AAssetManager_fromJava (env, manager);
  1200 
  1201   /* Initialize the directory tree.  */
  1202   asset = AAssetManager_open (asset_manager, "directory-tree",
  1203                               AASSET_MODE_BUFFER);
  1204 
  1205   if (!asset)
  1206     {
  1207       __android_log_print (ANDROID_LOG_FATAL, __func__,
  1208                            "Failed to open directory tree");
  1209       emacs_abort ();
  1210     }
  1211 
  1212   directory_tree = AAsset_getBuffer (asset);
  1213 
  1214   if (!directory_tree)
  1215     emacs_abort ();
  1216 
  1217   /* Now figure out how big the directory tree is, and compare the
  1218      first few bytes.  */
  1219   directory_tree_size = AAsset_getLength (asset);
  1220   if (directory_tree_size < 5
  1221       || memcmp (directory_tree, "EMACS", 5))
  1222     {
  1223       __android_log_print (ANDROID_LOG_FATAL, __func__,
  1224                            "Directory tree has bad magic");
  1225       emacs_abort ();
  1226     }
  1227 
  1228   /* Hold a VM reference to the asset manager to prevent the native
  1229      object from being deleted.  */
  1230   (*env)->NewGlobalRef (env, manager);
  1231 
  1232   /* Abort if there's no more memory for the global reference.  */
  1233   if ((*env)->ExceptionCheck (env))
  1234     abort ();
  1235 }
  1236 
  1237 
  1238 
  1239 /* Asset-to-file descriptor conversion.  */
  1240 
  1241 /* Pointer to the `ASharedMemory_create' function which is loaded
  1242    dynamically.  */
  1243 static int (*asharedmemory_create) (const char *, size_t);
  1244 
  1245 /* Do the same as android_hack_asset_fd, but use an unlinked temporary
  1246    file to cater to old Android kernels where ashmem files are not
  1247    readable.  */
  1248 
  1249 static int
  1250 android_hack_asset_fd_fallback (AAsset *asset)
  1251 {
  1252   int fd;
  1253   char filename[PATH_MAX];
  1254   size_t size;
  1255   void *mem;
  1256 
  1257   /* Assets must be small enough to fit in size_t, if off_t is
  1258      larger.  */
  1259   size = AAsset_getLength (asset);
  1260 
  1261   /* Get an unlinked file descriptor from a file in the cache
  1262      directory, which is guaranteed to only be written to by Emacs.
  1263      Creating an ashmem file descriptor and reading from it doesn't
  1264      work on these old Android versions.  */
  1265 
  1266   snprintf (filename, PATH_MAX, "%s/temp~unlinked.%d",
  1267             android_cache_dir, getpid ());
  1268   fd = open (filename, O_CREAT | O_RDWR | O_TRUNC,
  1269              S_IRUSR | S_IWUSR);
  1270 
  1271   if (fd < 0)
  1272     return -1;
  1273 
  1274   if (unlink (filename))
  1275     goto fail;
  1276 
  1277   if (ftruncate (fd, size))
  1278     goto fail;
  1279 
  1280   mem = mmap (NULL, size, PROT_WRITE, MAP_SHARED, fd, 0);
  1281   if (mem == MAP_FAILED)
  1282     {
  1283       __android_log_print (ANDROID_LOG_ERROR, __func__,
  1284                            "mmap: %s", strerror (errno));
  1285       goto fail;
  1286     }
  1287 
  1288   if (AAsset_read (asset, mem, size) != size)
  1289     {
  1290       /* Too little was read.  Close the file descriptor and
  1291          report an error.  */
  1292       __android_log_print (ANDROID_LOG_ERROR, __func__,
  1293                            "AAsset_read: %s", strerror (errno));
  1294       goto fail;
  1295     }
  1296 
  1297   munmap (mem, size);
  1298   return fd;
  1299 
  1300  fail:
  1301   close (fd);
  1302   return -1;
  1303 }
  1304 
  1305 /* Return whether or not shared memory file descriptors can also be
  1306    read from, and are thus suitable for creating asset files.
  1307 
  1308    This does not work on some ancient Android systems running old
  1309    versions of the kernel.  */
  1310 
  1311 static bool
  1312 android_detect_ashmem (void)
  1313 {
  1314   int fd, rc;
  1315   void *mem;
  1316   char test_buffer[10];
  1317 
  1318   memcpy (test_buffer, "abcdefghi", 10);
  1319 
  1320   /* Create the file descriptor to be used for the test.  */
  1321 
  1322   /* Android 28 and earlier let Emacs access /dev/ashmem directly, so
  1323      prefer that over using ASharedMemory.  */
  1324 
  1325   if (android_get_current_api_level () <= 28)
  1326     {
  1327       fd = open ("/dev/ashmem", O_RDWR);
  1328 
  1329       if (fd < 0)
  1330         return false;
  1331 
  1332       /* An empty name means the memory area will exist until the file
  1333          descriptor is closed, because no other process can
  1334          attach.  */
  1335       rc = ioctl (fd, ASHMEM_SET_NAME, "");
  1336 
  1337       if (rc < 0)
  1338         {
  1339           close (fd);
  1340           return false;
  1341         }
  1342 
  1343       rc = ioctl (fd, ASHMEM_SET_SIZE, sizeof test_buffer);
  1344 
  1345       if (rc < 0)
  1346         {
  1347           close (fd);
  1348           return false;
  1349         }
  1350     }
  1351   else
  1352     {
  1353       /* On the other hand, SELinux restrictions on Android 29 and
  1354          later require that Emacs use a system service to obtain
  1355          shared memory.  Load this dynamically, as this service is not
  1356          available on all versions of the NDK.  */
  1357 
  1358       if (!asharedmemory_create)
  1359         {
  1360           *(void **) (&asharedmemory_create)
  1361             = dlsym (RTLD_DEFAULT, "ASharedMemory_create");
  1362 
  1363           if (!asharedmemory_create)
  1364             {
  1365               __android_log_print (ANDROID_LOG_FATAL, __func__,
  1366                                    "dlsym: %s\n",
  1367                                    strerror (errno));
  1368               emacs_abort ();
  1369             }
  1370         }
  1371 
  1372       fd = (*asharedmemory_create) ("", sizeof test_buffer);
  1373 
  1374       if (fd < 0)
  1375         return false;
  1376     }
  1377 
  1378   /* Now map the resource and write the test contents.  */
  1379 
  1380   mem = mmap (NULL, sizeof test_buffer, PROT_WRITE,
  1381               MAP_SHARED, fd, 0);
  1382   if (mem == MAP_FAILED)
  1383     {
  1384       close (fd);
  1385       return false;
  1386     }
  1387 
  1388   /* Copy over the test contents.  */
  1389   memcpy (mem, test_buffer, sizeof test_buffer);
  1390 
  1391   /* Return anyway even if munmap fails.  */
  1392   munmap (mem, sizeof test_buffer);
  1393 
  1394   /* Try to read the content back into test_buffer.  If this does not
  1395      compare equal to the original string, or the read fails, then
  1396      ashmem descriptors are not readable on this system.  */
  1397 
  1398   if ((read (fd, test_buffer, sizeof test_buffer)
  1399        != sizeof test_buffer)
  1400       || memcmp (test_buffer, "abcdefghi", sizeof test_buffer))
  1401     {
  1402       __android_log_print (ANDROID_LOG_WARN, __func__,
  1403                            "/dev/ashmem does not produce real"
  1404                            " temporary files on this system, so"
  1405                            " Emacs will fall back to creating"
  1406                            " unlinked temporary files.");
  1407       close (fd);
  1408       return false;
  1409     }
  1410 
  1411   close (fd);
  1412   return true;
  1413 }
  1414 
  1415 /* Get a file descriptor backed by a temporary in-memory file for the
  1416    given asset.  */
  1417 
  1418 static int
  1419 android_hack_asset_fd (AAsset *asset)
  1420 {
  1421   static bool ashmem_readable_p;
  1422   static bool ashmem_initialized;
  1423   int fd, rc;
  1424   unsigned char *mem;
  1425   size_t size;
  1426 
  1427   /* The first time this function is called, try to determine whether
  1428      or not ashmem file descriptors can be read from.  */
  1429 
  1430   if (!ashmem_initialized)
  1431     ashmem_readable_p
  1432       = android_detect_ashmem ();
  1433   ashmem_initialized = true;
  1434 
  1435   /* If it isn't, fall back.  */
  1436 
  1437   if (!ashmem_readable_p)
  1438     return android_hack_asset_fd_fallback (asset);
  1439 
  1440   /* Assets must be small enough to fit in size_t, if off_t is
  1441      larger.  */
  1442   size = AAsset_getLength (asset);
  1443 
  1444   /* Android 28 and earlier let Emacs access /dev/ashmem directly, so
  1445      prefer that over using ASharedMemory.  */
  1446 
  1447   if (android_get_current_api_level () <= 28)
  1448     {
  1449       fd = open ("/dev/ashmem", O_RDWR);
  1450 
  1451       if (fd < 0)
  1452         return -1;
  1453 
  1454       /* An empty name means the memory area will exist until the file
  1455          descriptor is closed, because no other process can
  1456          attach.  */
  1457       rc = ioctl (fd, ASHMEM_SET_NAME, "");
  1458 
  1459       if (rc < 0)
  1460         {
  1461           __android_log_print (ANDROID_LOG_ERROR, __func__,
  1462                                "ioctl ASHMEM_SET_NAME: %s",
  1463                                strerror (errno));
  1464           close (fd);
  1465           return -1;
  1466         }
  1467 
  1468       rc = ioctl (fd, ASHMEM_SET_SIZE, size);
  1469 
  1470       if (rc < 0)
  1471         {
  1472           __android_log_print (ANDROID_LOG_ERROR, __func__,
  1473                                "ioctl ASHMEM_SET_SIZE: %s",
  1474                                strerror (errno));
  1475           close (fd);
  1476           return -1;
  1477         }
  1478 
  1479       if (!size)
  1480         return fd;
  1481 
  1482       /* Now map the resource.  */
  1483       mem = mmap (NULL, size, PROT_WRITE, MAP_SHARED, fd, 0);
  1484       if (mem == MAP_FAILED)
  1485         {
  1486           __android_log_print (ANDROID_LOG_ERROR, __func__,
  1487                                "mmap: %s", strerror (errno));
  1488           close (fd);
  1489           return -1;
  1490         }
  1491 
  1492       if (AAsset_read (asset, mem, size) != size)
  1493         {
  1494           /* Too little was read.  Close the file descriptor and
  1495              report an error.  */
  1496           __android_log_print (ANDROID_LOG_ERROR, __func__,
  1497                                "AAsset_read: %s", strerror (errno));
  1498           close (fd);
  1499           return -1;
  1500         }
  1501 
  1502       /* Return anyway even if munmap fails.  */
  1503       munmap (mem, size);
  1504       return fd;
  1505     }
  1506 
  1507   /* On the other hand, SELinux restrictions on Android 29 and later
  1508      require that Emacs use a system service to obtain shared memory.
  1509      Load this dynamically, as this service is not available on all
  1510      versions of the NDK.  */
  1511 
  1512   if (!asharedmemory_create)
  1513     {
  1514       *(void **) (&asharedmemory_create)
  1515         = dlsym (RTLD_DEFAULT, "ASharedMemory_create");
  1516 
  1517       if (!asharedmemory_create)
  1518         {
  1519           __android_log_print (ANDROID_LOG_FATAL, __func__,
  1520                                "dlsym: %s\n",
  1521                                strerror (errno));
  1522           emacs_abort ();
  1523         }
  1524     }
  1525 
  1526   fd = (*asharedmemory_create) ("", size);
  1527 
  1528   if (fd < 0)
  1529     {
  1530       __android_log_print (ANDROID_LOG_ERROR, __func__,
  1531                            "ASharedMemory_create: %s",
  1532                            strerror (errno));
  1533       return -1;
  1534     }
  1535 
  1536   /* Now map the resource.  */
  1537   mem = mmap (NULL, size, PROT_WRITE, MAP_SHARED, fd, 0);
  1538   if (mem == MAP_FAILED)
  1539     {
  1540       __android_log_print (ANDROID_LOG_ERROR, __func__,
  1541                            "mmap: %s", strerror (errno));
  1542       close (fd);
  1543       return -1;
  1544     }
  1545 
  1546   if (AAsset_read (asset, mem, size) != size)
  1547     {
  1548       /* Too little was read.  Close the file descriptor and
  1549          report an error.  */
  1550       __android_log_print (ANDROID_LOG_ERROR, __func__,
  1551                            "AAsset_read: %s", strerror (errno));
  1552       close (fd);
  1553       return -1;
  1554     }
  1555 
  1556   /* Return anyway even if munmap fails.  */
  1557   munmap (mem, size);
  1558   return fd;
  1559 }
  1560 
  1561 
  1562 
  1563 /* ``Asset file system'' vnode implementation.  These vnodes map to
  1564    asset files within the application package, provided by the Android
  1565    ``asset manager''.  */
  1566 
  1567 struct android_afs_vnode
  1568 {
  1569   /* The vnode data itself.  */
  1570   struct android_vnode vnode;
  1571 
  1572   /* Length of the name without a trailing null byte.  */
  1573   size_t name_length;
  1574 
  1575   /* Name of the vnode.  */
  1576   char *name;
  1577 };
  1578 
  1579 struct android_afs_vdir
  1580 {
  1581   /* The directory function table.  */
  1582   struct android_vdir vdir;
  1583 
  1584   /* The next directory stream in `all_afs_vdirs'.  */
  1585   struct android_afs_vdir *next;
  1586 
  1587   /* Pointer to the directory in directory_tree.  */
  1588   char *asset_dir;
  1589 
  1590   /* And the end of the files in asset_dir.  */
  1591   char *asset_limit;
  1592 
  1593   /* Path to the directory relative to /.  */
  1594   char *asset_file;
  1595 
  1596   /* File descriptor representing this directory stream, or NULL.  */
  1597   int fd;
  1598 };
  1599 
  1600 struct android_afs_open_fd
  1601 {
  1602   /* The next table entry.  */
  1603   struct android_afs_open_fd *next;
  1604 
  1605   /* The open file descriptor.  */
  1606   int fd;
  1607 
  1608   /* The stat buffer associated with this entry.  */
  1609   struct stat statb;
  1610 };
  1611 
  1612 static struct android_vnode *android_afs_name (struct android_vnode *,
  1613                                                char *, size_t);
  1614 static int android_afs_open (struct android_vnode *, int,
  1615                              mode_t, bool, int *, AAsset **);
  1616 static void android_afs_close (struct android_vnode *);
  1617 static int android_afs_unlink (struct android_vnode *);
  1618 static int android_afs_symlink (const char *, struct android_vnode *);
  1619 static int android_afs_rmdir (struct android_vnode *);
  1620 static int android_afs_rename (struct android_vnode *,
  1621                                struct android_vnode *, bool);
  1622 static int android_afs_stat (struct android_vnode *, struct stat *);
  1623 static int android_afs_access (struct android_vnode *, int);
  1624 static int android_afs_mkdir (struct android_vnode *, mode_t);
  1625 static int android_afs_chmod (struct android_vnode *, mode_t, int);
  1626 static ssize_t android_afs_readlink (struct android_vnode *, char *,
  1627                                      size_t);
  1628 static struct android_vdir *android_afs_opendir (struct android_vnode *);
  1629 
  1630 /* Vector of VFS operations associated with asset VFS nodes.  */
  1631 
  1632 static struct android_vops afs_vfs_ops =
  1633   {
  1634     android_afs_name,
  1635     android_afs_open,
  1636     android_afs_close,
  1637     android_afs_unlink,
  1638     android_afs_symlink,
  1639     android_afs_rmdir,
  1640     android_afs_rename,
  1641     android_afs_stat,
  1642     android_afs_access,
  1643     android_afs_mkdir,
  1644     android_afs_chmod,
  1645     android_afs_readlink,
  1646     android_afs_opendir,
  1647   };
  1648 
  1649 /* Chain consisting of all open asset directory streams.  */
  1650 static struct android_afs_vdir *all_afs_vdirs;
  1651 
  1652 /* List linking open file descriptors to asset information.  This
  1653    assumes Emacs does not use dup on regular files.  */
  1654 static struct android_afs_open_fd *afs_file_descriptors;
  1655 
  1656 static struct android_vnode *
  1657 android_afs_name (struct android_vnode *vnode, char *name,
  1658                   size_t length)
  1659 {
  1660   size_t j;
  1661   char *remainder, *fill;
  1662   struct android_afs_vnode *vp, *input;
  1663   struct android_afs_vnode temp;
  1664 
  1665   input = (struct android_afs_vnode *) vnode;
  1666 
  1667   /* Canonicalize NAME.  */
  1668   remainder = android_vfs_canonicalize_name (name, &length);
  1669 
  1670   /* If remainder is set, it's a name relative to the parent
  1671      vnode.  */
  1672   if (remainder)
  1673     goto parent_vnode;
  1674 
  1675   /* Allocate a new vnode.  */
  1676   vp = xmalloc (sizeof *vp);
  1677 
  1678   /* See the specified name is empty.  */
  1679 
  1680   if (length < 1)
  1681     {
  1682       memcpy (vp, vnode, sizeof *vp);
  1683       vp->name = xstrdup (vp->name);
  1684       return &vp->vnode;
  1685     }
  1686 
  1687   /* Recompute length.  */
  1688   vp->vnode.ops = &afs_vfs_ops;
  1689   vp->vnode.type = ANDROID_VNODE_AFS;
  1690   vp->vnode.flags = 0;
  1691 
  1692   /* Generate the new name of the vnode.  Remove any trailing slash
  1693      from vp->name.  */
  1694 
  1695   vp->name_length = input->name_length + length;
  1696   vp->name = xmalloc (vp->name_length + 2);
  1697 
  1698   /* Copy the parent name over.  */
  1699   fill = mempcpy (vp->name, input->name, input->name_length);
  1700 
  1701   /* Check if it contains a trailing slash.  input->name cannot be
  1702      empty, as the root vnode's name is `/'.  */
  1703 
  1704   if (fill[-1] != '/' && *name != '/')
  1705     /* If not, append a trailing slash and adjust vp->name_length
  1706        correspondingly.  */
  1707     *fill++ = '/', vp->name_length++;
  1708   else if (fill[-1] == '/' && *name == '/')
  1709     /* If name has a leading slash and fill does too, move fill
  1710        backwards so that name's slash will override that of fill.  */
  1711     fill--, vp->name_length--;
  1712 
  1713   /* Now copy NAME.  */
  1714   fill = mempcpy (fill, name, length);
  1715 
  1716   /* And NULL terminate fill.  */
  1717   *fill = '\0';
  1718   return &vp->vnode;
  1719 
  1720  parent_vnode:
  1721   /* .. was encountered and the parent couldn't be found through
  1722      stripping off preceding components.
  1723 
  1724      Find the parent vnode and name the rest of NAME starting from
  1725      there.  */
  1726 
  1727   if (input->name_length == 1)
  1728     /* This is the vnode representing the /assets directory... */
  1729     vnode = &root_vnode.vnode;
  1730   else
  1731     {
  1732       /* Create a temporary asset vnode within the parent and use it
  1733          instead.  First, establish the length of vp->name before its
  1734          last component.  */
  1735 
  1736       for (j = input->name_length - 1; j; --j)
  1737         {
  1738           if (input->name[j - 1] == '/')
  1739             break;
  1740         }
  1741 
  1742       /* There must be at least one leading directory separator in an
  1743          asset vnode's `name' field.  */
  1744 
  1745       if (!j)
  1746         abort ();
  1747 
  1748       /* j is now the length of the string minus the size of its last
  1749          component.  Create a temporary vnode with that as its
  1750          name.  */
  1751 
  1752       temp.vnode.ops = &afs_vfs_ops;
  1753       temp.vnode.type = ANDROID_VNODE_AFS;
  1754       temp.vnode.flags = 0;
  1755       temp.name_length = j;
  1756       temp.name = xmalloc (j + 1);
  1757       fill = mempcpy (temp.name, input->name, j);
  1758       *fill = '\0';
  1759 
  1760       /* Search for the remainder of NAME relative to its parent.  */
  1761       vnode = android_afs_name (&temp.vnode, remainder,
  1762                                 strlen (remainder));
  1763       xfree (temp.name);
  1764       return vnode;
  1765     }
  1766 
  1767   return (*vnode->ops->name) (vnode, remainder, strlen (remainder));
  1768 }
  1769 
  1770 /* Find the vnode designated by the normalized NAME relative to the
  1771    root of the asset file system.  NAME may be modified, and must be
  1772    LENGTH bytes long, excluding its terminating NULL byte.  */
  1773 
  1774 static struct android_vnode *
  1775 android_afs_initial (char *name, size_t length)
  1776 {
  1777   struct android_afs_vnode temp;
  1778 
  1779   /* Create a temporary vnode at the root of the asset file
  1780      system.  */
  1781 
  1782   temp.vnode.ops = &afs_vfs_ops;
  1783   temp.vnode.type = ANDROID_VNODE_AFS;
  1784   temp.vnode.flags = 0;
  1785   temp.name_length = 1;
  1786   temp.name = (char *) "/";
  1787 
  1788   /* Try to name this vnode.  If NAME is empty, it will be duplicated
  1789      instead.  */
  1790   return android_afs_name (&temp.vnode, name, length);
  1791 }
  1792 
  1793 /* Make FD close-on-exec.  If any system call fails, do not abort, but
  1794    log a warning to the system log.  */
  1795 
  1796 static void
  1797 android_close_on_exec (int fd)
  1798 {
  1799   int flags, rc;
  1800 
  1801   flags = fcntl (fd, F_GETFD);
  1802 
  1803   if (flags < 0)
  1804     {
  1805       __android_log_print (ANDROID_LOG_WARN, __func__,
  1806                            "fcntl: %s", strerror (errno));
  1807       return;
  1808     }
  1809 
  1810   rc = fcntl (fd, F_SETFD, flags | O_CLOEXEC);
  1811 
  1812   if (rc < 0)
  1813     {
  1814       __android_log_print (ANDROID_LOG_WARN, __func__,
  1815                            "fcntl: %s", strerror (errno));
  1816       return;
  1817     }
  1818 }
  1819 
  1820 static int
  1821 android_afs_open (struct android_vnode *vnode, int flags,
  1822                   mode_t mode, bool asset_p, int *fd_return,
  1823                   AAsset **asset_return)
  1824 {
  1825   AAsset *asset;
  1826   struct android_afs_vnode *vp;
  1827   const char *asset_dir;
  1828   int fd;
  1829   struct android_afs_open_fd *info;
  1830 
  1831   vp = (struct android_afs_vnode *) vnode;
  1832 
  1833   /* Return suitable error indications for unsupported file
  1834      operations.  */
  1835 
  1836   if ((flags & O_WRONLY) || (flags & O_RDWR))
  1837     {
  1838       errno = EROFS;
  1839       return -1;
  1840     }
  1841 
  1842   if (flags & O_DIRECTORY)
  1843     {
  1844       errno = ENOSYS;
  1845       return -1;
  1846     }
  1847 
  1848   /* Now try to open this asset.  Asset manager APIs expect there to
  1849      be no trailing directory separator.  */
  1850   asset = AAssetManager_open (asset_manager, vp->name + 1,
  1851                               AASSET_MODE_STREAMING);
  1852 
  1853   /* If it can't be opened, return an error indication.  */
  1854 
  1855   if (!asset)
  1856     {
  1857       /* Scan the directory tree for this file.  */
  1858       asset_dir = android_scan_directory_tree (vp->name, NULL);
  1859 
  1860       /* Default errno to ENOTENT.  */
  1861       errno = ENOENT;
  1862 
  1863       /* Maybe the caller wants to open a directory vnode as a
  1864          file?  */
  1865 
  1866       if (asset_dir && android_is_directory (asset_dir))
  1867         /* In that case, set errno to ENOSYS.  */
  1868         errno = ENOSYS;
  1869 
  1870       return -1;
  1871     }
  1872 
  1873   /* An asset has been opened.  If the caller wants a file descriptor,
  1874      a temporary one must be created and the file contents read
  1875      inside.  */
  1876 
  1877   if (!asset_p)
  1878     {
  1879       /* Create a shared memory file descriptor containing the asset
  1880          contents.
  1881 
  1882          The documentation misleads people into thinking that
  1883          AAsset_openFileDescriptor does precisely this.  However, it
  1884          instead returns an offset into any uncompressed assets in the
  1885          ZIP archive.  This cannot be found in its documentation.  */
  1886 
  1887       fd = android_hack_asset_fd (asset);
  1888 
  1889       if (fd == -1)
  1890         {
  1891           AAsset_close (asset);
  1892           errno = EIO;
  1893           return -1;
  1894         }
  1895 
  1896       /* If O_CLOEXEC is specified, make the file descriptor close on
  1897          exec too.  */
  1898 
  1899       if (flags & O_CLOEXEC)
  1900         android_close_on_exec (fd);
  1901 
  1902       /* Keep a record linking ``hacked'' file descriptors with
  1903          their file status.  */
  1904       info = xzalloc (sizeof *info);
  1905       info->fd   = fd;
  1906       info->next = afs_file_descriptors;
  1907 
  1908       /* Fill in some information that will be reported to
  1909          callers of android_fstat, among others.  */
  1910       info->statb.st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH;
  1911 
  1912       /* Owned by root.  */
  1913       info->statb.st_uid = 0;
  1914       info->statb.st_gid = 0;
  1915 
  1916       /* Concoct a nonexistent device and an inode number.  */
  1917       info->statb.st_dev = -1;
  1918       info->statb.st_ino = 0;
  1919 
  1920       /* Size of the file.  */
  1921       info->statb.st_size = AAsset_getLength (asset);
  1922 
  1923       /* Chain info onto afs_file_descriptors.  */
  1924       afs_file_descriptors = info;
  1925 
  1926       AAsset_close (asset);
  1927 
  1928       /* Return the file descriptor.  */
  1929       *fd_return = fd;
  1930       return 0;
  1931     }
  1932 
  1933   /* Return the asset itself.  */
  1934   *asset_return = asset;
  1935   return 1;
  1936 }
  1937 
  1938 static void
  1939 android_afs_close (struct android_vnode *vnode)
  1940 {
  1941   struct android_afs_vnode *vp;
  1942   int save_errno;
  1943 
  1944   save_errno = errno;
  1945   vp = (struct android_afs_vnode *) vnode;
  1946   xfree (vp->name);
  1947   xfree (vp);
  1948   errno = save_errno;
  1949 }
  1950 
  1951 static int
  1952 android_afs_unlink (struct android_vnode *vnode)
  1953 {
  1954   const char *dir;
  1955   struct android_afs_vnode *vp;
  1956 
  1957   /* If the vnode already exists, return EROFS.  Else, return
  1958      ENOENT.  */
  1959 
  1960   vp = (struct android_afs_vnode *) vnode;
  1961   dir = android_scan_directory_tree (vp->name, NULL);
  1962 
  1963   if (dir)
  1964     errno = EROFS;
  1965   else
  1966     errno = ENOENT;
  1967 
  1968   return -1;
  1969 }
  1970 
  1971 static int
  1972 android_afs_symlink (const char *linkname, struct android_vnode *vnode)
  1973 {
  1974   struct android_afs_vnode *vp;
  1975 
  1976   /* If this vnode already exists, return EEXIST.  */
  1977   vp = (struct android_afs_vnode *) vnode;
  1978 
  1979   if (android_scan_directory_tree (vp->name, NULL))
  1980     {
  1981       errno = EEXIST;
  1982       return -1;
  1983     }
  1984 
  1985   /* Symlinks aren't supported on this (read-only) ``file system'',
  1986      so return -1 with EROFS.  */
  1987   errno = EROFS;
  1988   return -1;
  1989 }
  1990 
  1991 static int
  1992 android_afs_rmdir (struct android_vnode *vnode)
  1993 {
  1994   const char *dir;
  1995   struct android_afs_vnode *vp;
  1996 
  1997   /* If the vnode already exists and is a directory, return EROFS.
  1998      Else, return ENOTDIR or ENOENT.  */
  1999 
  2000   vp = (struct android_afs_vnode *) vnode;
  2001   dir = android_scan_directory_tree (vp->name, NULL);
  2002 
  2003   if (dir && android_is_directory (dir))
  2004     errno = EROFS;
  2005   else if (dir)
  2006     errno = ENOTDIR;
  2007   else
  2008     errno = ENOENT;
  2009 
  2010   return -1;
  2011 }
  2012 
  2013 static int
  2014 android_afs_rename (struct android_vnode *src, struct android_vnode *dst,
  2015                     bool keep_existing)
  2016 {
  2017   /* If src and dst are different kinds of vnodes, return EXDEV.
  2018      Else, return EROFS.  */
  2019 
  2020   errno = EROFS;
  2021   if (src->type != dst->type)
  2022     errno = EXDEV;
  2023 
  2024   return -1;
  2025 }
  2026 
  2027 static int
  2028 android_afs_stat (struct android_vnode *vnode, struct stat *statb)
  2029 {
  2030   const char *dir;
  2031   struct android_afs_vnode *vp;
  2032   AAsset *asset_desc;
  2033 
  2034   /* Scan for the vnode to see whether or not it exists.  */
  2035 
  2036   vp = (struct android_afs_vnode *) vnode;
  2037   dir = android_scan_directory_tree (vp->name, NULL);
  2038 
  2039   if (!dir)
  2040     {
  2041       /* Return ENOENT; whether the lookup failed because directory
  2042          components within vp->path weren't really directories is not
  2043          important to Emacs's error reporting.  */
  2044       errno = ENOENT;
  2045       return -1;
  2046     }
  2047 
  2048   if (android_is_directory (dir))
  2049     {
  2050       memset (statb, 0, sizeof *statb);
  2051 
  2052       /* Fill in the stat buffer.  */
  2053       statb->st_mode = S_IFDIR | S_IRUSR | S_IRGRP | S_IROTH;
  2054 
  2055       /* Grant search permissions as well.  */
  2056       statb->st_mode |= S_IXUSR | S_IXGRP | S_IXOTH;
  2057 
  2058       /* Concoct a nonexistent device and an inode number.  */
  2059       statb->st_dev = -1;
  2060       statb->st_ino = 0;
  2061       return 0;
  2062     }
  2063 
  2064   /* AASSET_MODE_STREAMING is fastest here.  */
  2065   asset_desc = AAssetManager_open (asset_manager, vp->name + 1,
  2066                                    AASSET_MODE_STREAMING);
  2067 
  2068   if (!asset_desc)
  2069     {
  2070       /* If the asset exists in the directory tree but can't be
  2071          located by the asset manager, report OOM.  */
  2072       errno = ENOMEM;
  2073       return 1;
  2074     }
  2075 
  2076   memset (statb, 0, sizeof *statb);
  2077 
  2078   /* Fill in the stat buffer.  */
  2079   statb->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH;
  2080   statb->st_dev = -1;
  2081   statb->st_ino = 0;
  2082   statb->st_size = AAsset_getLength (asset_desc);
  2083 
  2084   /* Close the asset.  */
  2085   AAsset_close (asset_desc);
  2086   return 0;
  2087 }
  2088 
  2089 static int
  2090 android_afs_access (struct android_vnode *vnode, int mode)
  2091 {
  2092   const char *dir;
  2093   struct android_afs_vnode *vp;
  2094 
  2095   /* Validate MODE.  */
  2096 
  2097   if (mode != F_OK && !(mode & (W_OK | X_OK | R_OK)))
  2098     {
  2099       errno = EINVAL;
  2100       return -1;
  2101     }
  2102 
  2103   /* Scan for the vnode to see whether or not it exists.  */
  2104 
  2105   vp = (struct android_afs_vnode *) vnode;
  2106   dir = android_scan_directory_tree (vp->name, NULL);
  2107 
  2108   if (dir)
  2109     {
  2110       /* It exists.  If MODE contains W_OK or X_OK, return
  2111          EACCESS.  */
  2112 
  2113       if (mode & (W_OK | X_OK))
  2114         {
  2115           errno = EACCES;
  2116           return -1;
  2117         }
  2118 
  2119       /* If vp->name is a directory and DIR isn't, return ENOTDIR.  */
  2120 
  2121       if (vp->name[vp->name_length] == '/'
  2122           && !android_is_directory (dir))
  2123         {
  2124           errno = ENOTDIR;
  2125           return -1;
  2126         }
  2127 
  2128       return 0;
  2129     }
  2130 
  2131   errno = ENOENT;
  2132   return -1;
  2133 }
  2134 
  2135 static int
  2136 android_afs_mkdir (struct android_vnode *vnode, mode_t mode)
  2137 {
  2138   struct android_afs_vnode *vp;
  2139   const char *dir;
  2140 
  2141   /* If the vnode already exists, return EEXIST in lieu of EROFS.  */
  2142 
  2143   vp = (struct android_afs_vnode *) vnode;
  2144   dir = android_scan_directory_tree (vp->name, NULL);
  2145 
  2146   if (dir)
  2147     errno = EEXIST;
  2148   else
  2149     errno = EROFS;
  2150 
  2151   return -1;
  2152 }
  2153 
  2154 static int
  2155 android_afs_chmod (struct android_vnode *vnode, mode_t mode,
  2156                    int flags)
  2157 {
  2158   errno = EROFS;
  2159   return -1;
  2160 }
  2161 
  2162 static ssize_t
  2163 android_afs_readlink (struct android_vnode *vnode, char *buffer,
  2164                       size_t size)
  2165 {
  2166   struct android_afs_vnode *vp;
  2167   const char *dir;
  2168 
  2169   vp = (struct android_afs_vnode *) vnode;
  2170   dir = android_scan_directory_tree (vp->name, NULL);
  2171 
  2172   /* As there are no symlinks in /assets, just return -1 with errno
  2173      set to a reasonable value contingent upon whether VP->name
  2174      actually exists.  */
  2175 
  2176   if (dir)
  2177     errno = EINVAL;
  2178   else
  2179     errno = ENOENT;
  2180 
  2181   return -1;
  2182 }
  2183 
  2184 static struct dirent *
  2185 android_afs_readdir (struct android_vdir *vdir)
  2186 {
  2187   static struct dirent dirent;
  2188   const char *last;
  2189   struct android_afs_vdir *dir;
  2190 
  2191   dir = (struct android_afs_vdir *) vdir;
  2192 
  2193   /* There are no more files to read.  */
  2194   if (dir->asset_dir >= dir->asset_limit)
  2195     return NULL;
  2196 
  2197   /* Otherwise, scan forward looking for the next NULL byte.  */
  2198   last = memchr (dir->asset_dir, 0,
  2199                  dir->asset_limit - dir->asset_dir);
  2200 
  2201   /* No more NULL bytes remain.  */
  2202   if (!last)
  2203     return NULL;
  2204 
  2205   /* Forward last past the NULL byte.  */
  2206   last++;
  2207 
  2208   /* Make sure it is still within the directory tree.  */
  2209   if (last >= directory_tree + directory_tree_size)
  2210     return NULL;
  2211 
  2212   /* Now, fill in the dirent with the name.  */
  2213   memset (&dirent, 0, sizeof dirent);
  2214   dirent.d_ino = 0;
  2215   dirent.d_off = 0;
  2216   dirent.d_reclen = sizeof dirent;
  2217 
  2218   /* Note that dir->asset_dir is actually a NULL terminated
  2219      string.  */
  2220   memcpy (dirent.d_name, dir->asset_dir,
  2221           MIN (sizeof dirent.d_name,
  2222                last - dir->asset_dir));
  2223   dirent.d_name[sizeof dirent.d_name - 1] = '\0';
  2224 
  2225   /* Strip off the trailing slash, if any.  */
  2226   if (dirent.d_name[MIN (sizeof dirent.d_name,
  2227                          last - dir->asset_dir)
  2228                     - 2] == '/')
  2229     dirent.d_name[MIN (sizeof dirent.d_name,
  2230                        last - dir->asset_dir)
  2231                   - 2] = '\0';
  2232 
  2233   /* If this is not a directory, return DT_REG.  Otherwise, return
  2234      DT_DIR.  */
  2235 
  2236   if (last - 2 >= directory_tree && last[-2] == '/')
  2237     dirent.d_type = DT_DIR;
  2238   else
  2239     dirent.d_type = DT_REG;
  2240 
  2241   /* Forward dir->asset_dir to the file past last.  */
  2242   dir->asset_dir = ((char *) directory_tree
  2243                     + android_extract_long ((char *) last));
  2244 
  2245   return &dirent;
  2246 }
  2247 
  2248 static void
  2249 android_afs_closedir (struct android_vdir *vdir)
  2250 {
  2251   struct android_afs_vdir *dir, **next, *tem;
  2252 
  2253   dir = (struct android_afs_vdir *) vdir;
  2254 
  2255   /* If the ``directory file descriptor'' has been opened, close
  2256      it.  */
  2257 
  2258   if (dir->fd != -1)
  2259     close (dir->fd);
  2260 
  2261   xfree (dir->asset_file);
  2262 
  2263   /* Now unlink this directory.  */
  2264 
  2265   for (next = &all_afs_vdirs; (tem = *next);)
  2266     {
  2267       if (tem == dir)
  2268         *next = dir->next;
  2269       else
  2270         next = &(*next)->next;
  2271     }
  2272 
  2273   /* Free the directory itself.  */
  2274 
  2275   xfree (dir);
  2276 }
  2277 
  2278 static int
  2279 android_afs_dirfd (struct android_vdir *vdir)
  2280 {
  2281   struct android_afs_vdir *dir;
  2282 
  2283   dir = (struct android_afs_vdir *) vdir;
  2284 
  2285   /* Since `android_afs_opendir' tries to avoid opening a file
  2286      descriptor if readdir isn't called, dirfd can fail if open fails.
  2287 
  2288      open sets errno to a set of errors different from what POSIX
  2289      stipulates for dirfd, but for ease of implementation the open
  2290      errors are used instead.  */
  2291 
  2292   if (dir->fd >= 0)
  2293     return dir->fd;
  2294 
  2295   dir->fd = open ("/dev/null", O_RDONLY | O_CLOEXEC);
  2296   return dir->fd;
  2297 }
  2298 
  2299 static struct android_vdir *
  2300 android_afs_opendir (struct android_vnode *vnode)
  2301 {
  2302   char *asset_dir;
  2303   struct android_afs_vdir *dir;
  2304   struct android_afs_vnode *vp;
  2305   size_t limit;
  2306 
  2307   vp = (struct android_afs_vnode *) vnode;
  2308 
  2309   /* Scan for the asset directory by vp->name.  */
  2310 
  2311   asset_dir
  2312     = (char *) android_scan_directory_tree (vp->name, &limit);
  2313 
  2314   if (!asset_dir)
  2315     {
  2316       errno = ENOENT;
  2317       return NULL;
  2318     }
  2319 
  2320   /* Verify that asset_dir is indeed a directory.  */
  2321 
  2322   if (!android_is_directory (asset_dir))
  2323     {
  2324       errno = ENOTDIR;
  2325       return NULL;
  2326     }
  2327 
  2328   /* Fill in the directory stream.  */
  2329   dir = xmalloc (sizeof *dir);
  2330   dir->vdir.readdir = android_afs_readdir;
  2331   dir->vdir.closedir = android_afs_closedir;
  2332   dir->vdir.dirfd = android_afs_dirfd;
  2333   dir->asset_dir = asset_dir;
  2334   dir->asset_limit = (char *) directory_tree + limit;
  2335   dir->fd = -1;
  2336   dir->asset_file = xzalloc (vp->name_length + 2);
  2337   strcpy (dir->asset_file, vp->name);
  2338 
  2339   /* Make sure dir->asset_file is terminated with /.  */
  2340   if (dir->asset_file[vp->name_length - 1] != '/')
  2341     dir->asset_file[vp->name_length] = '/';
  2342 
  2343   /* Make sure dir->asset_limit is within bounds.  It is a limit,
  2344      and as such can be exactly one byte past directory_tree.  */
  2345   if (dir->asset_limit > directory_tree + directory_tree_size)
  2346     {
  2347       xfree (dir);
  2348       xfree (dir->asset_file);
  2349       errno = EACCES;
  2350       return NULL;
  2351     }
  2352 
  2353   dir->next = all_afs_vdirs;
  2354   all_afs_vdirs = dir;
  2355   return &dir->vdir;
  2356 }
  2357 
  2358 /* Return the file name corresponding to DIRFD if it is a
  2359    ``directory'' file descriptor returned by `android_afs_dirfd' or
  2360    NULL otherwise.  These file names are relative to the `/assets'
  2361    directory, but with a leading separator character.  */
  2362 
  2363 static char *
  2364 android_afs_get_directory_name (int dirfd)
  2365 {
  2366   struct android_afs_vdir *dir;
  2367 
  2368   for (dir = all_afs_vdirs; dir; dir = dir->next)
  2369     {
  2370       if (dir->fd == dirfd && dirfd != -1)
  2371         return dir->asset_file;
  2372     }
  2373 
  2374   return NULL;
  2375 }
  2376 
  2377 
  2378 
  2379 struct android_content_vdir
  2380 {
  2381   /* The directory function table.  */
  2382   struct android_vdir vdir;
  2383 
  2384   /* The next directory stream in `all_content_vdirs'.  */
  2385   struct android_content_vdir *next;
  2386 
  2387   /* Pointer to the next file to return.  */
  2388   const char **next_name;
  2389 
  2390   /* Temporary file descriptor used to identify this directory to
  2391      at-funcs, or -1.  */
  2392   int fd;
  2393 };
  2394 
  2395 static struct android_vnode *android_authority_initial (char *, size_t);
  2396 static struct android_vnode *android_saf_root_initial (char *, size_t);
  2397 
  2398 /* Content provider meta-interface.  This implements a vnode at
  2399    /content, which is a directory itself containing two additional
  2400    directories.
  2401 
  2402    /content/storage only exists on Android 5.0 and later, and contains
  2403    a list of each directory tree Emacs has been granted permanent
  2404    access to through the Storage Access Framework.
  2405 
  2406    /content/by-authority exists on Android 4.4 and later; it contains
  2407    no directories, but provides a `name' function that converts
  2408    children into content URIs.  */
  2409 
  2410 static struct android_vnode *android_content_name (struct android_vnode *,
  2411                                                    char *, size_t);
  2412 static int android_content_open (struct android_vnode *, int,
  2413                                  mode_t, bool, int *, AAsset **);
  2414 static void android_content_close (struct android_vnode *);
  2415 static int android_content_unlink (struct android_vnode *);
  2416 static int android_content_symlink (const char *, struct android_vnode *);
  2417 static int android_content_rmdir (struct android_vnode *);
  2418 static int android_content_rename (struct android_vnode *,
  2419                                    struct android_vnode *, bool);
  2420 static int android_content_stat (struct android_vnode *, struct stat *);
  2421 static int android_content_access (struct android_vnode *, int);
  2422 static int android_content_mkdir (struct android_vnode *, mode_t);
  2423 static int android_content_chmod (struct android_vnode *, mode_t, int);
  2424 static ssize_t android_content_readlink (struct android_vnode *, char *,
  2425                                          size_t);
  2426 static struct android_vdir *android_content_opendir (struct android_vnode *);
  2427 
  2428 /* Vector of VFS operations associated with the content VFS node.  */
  2429 
  2430 static struct android_vops content_vfs_ops =
  2431   {
  2432     android_content_name,
  2433     android_content_open,
  2434     android_content_close,
  2435     android_content_unlink,
  2436     android_content_symlink,
  2437     android_content_rmdir,
  2438     android_content_rename,
  2439     android_content_stat,
  2440     android_content_access,
  2441     android_content_mkdir,
  2442     android_content_chmod,
  2443     android_content_readlink,
  2444     android_content_opendir,
  2445   };
  2446 
  2447 /* Table of directories contained within a top-level vnode.  */
  2448 
  2449 static const char *content_directory_contents[] =
  2450   {
  2451     "storage", "by-authority",
  2452   };
  2453 
  2454 /* Chain consisting of all open content directory streams.  */
  2455 static struct android_content_vdir *all_content_vdirs;
  2456 
  2457 static struct android_vnode *
  2458 android_content_name (struct android_vnode *vnode, char *name,
  2459                       size_t length)
  2460 {
  2461   char *remainder;
  2462   struct android_vnode *vp;
  2463   char *component_end;
  2464   struct android_special_vnode *special;
  2465   size_t i;
  2466   int api;
  2467 
  2468   static struct android_special_vnode content_vnodes[] = {
  2469     { "storage", 7, android_saf_root_initial,        },
  2470     { "by-authority", 12, android_authority_initial, },
  2471   };
  2472 
  2473   /* Canonicalize NAME.  */
  2474   remainder = android_vfs_canonicalize_name (name, &length);
  2475 
  2476   /* If remainder is set, it's a name relative to the root vnode.  */
  2477   if (remainder)
  2478     goto parent_vnode;
  2479 
  2480   /* If LENGTH is empty or NAME is a single directory separator,
  2481      return a copy of this vnode.  */
  2482 
  2483   if (length < 1 || (*name == '/' && length == 1))
  2484     {
  2485       vp = xmalloc (sizeof *vp);
  2486       memcpy (vp, vnode, sizeof *vp);
  2487       return vp;
  2488     }
  2489 
  2490   api = android_get_current_api_level ();
  2491 
  2492   /* If NAME starts with a directory separator, move it past that.  */
  2493 
  2494   if (*name == '/')
  2495     name++, length -= 1;
  2496 
  2497   /* Look for the first directory separator.  */
  2498   component_end = strchr (name, '/');
  2499 
  2500   /* If not there, use name + length.  */
  2501 
  2502   if (!component_end)
  2503     component_end = name + length;
  2504   else
  2505     /* Move past the separator character.  */
  2506     component_end++;
  2507 
  2508   /* Now, find out if the first component is a special vnode; if so,
  2509      call its root lookup function with the rest of NAME there.  */
  2510 
  2511   if (api < 19)
  2512     i = 2;
  2513   else if (api < 21)
  2514     i = 1;
  2515   else
  2516     i = 0;
  2517 
  2518   for (; i < ARRAYELTS (content_vnodes); ++i)
  2519     {
  2520       special = &content_vnodes[i];
  2521 
  2522       if (component_end - name == special->length
  2523           && !memcmp (special->name, name, special->length))
  2524         return (*special->initial) (component_end,
  2525                                     length - special->length);
  2526 
  2527       /* Detect the case where a special is named with a trailing
  2528          directory separator.  */
  2529 
  2530       if (component_end - name == special->length + 1
  2531           && !memcmp (special->name, name, special->length)
  2532           && name[special->length] == '/')
  2533         /* Make sure to include the directory separator.  */
  2534         return (*special->initial) (component_end - 1,
  2535                                     length - special->length);
  2536     }
  2537 
  2538   errno = ENOENT;
  2539   return NULL;
  2540 
  2541  parent_vnode:
  2542   /* The parent of this vnode is always the root filesystem.  */
  2543   vp = &root_vnode.vnode;
  2544   return (*vnode->ops->name) (vnode, remainder, strlen (remainder));
  2545 }
  2546 
  2547 static int
  2548 android_content_open (struct android_vnode *vnode, int flags,
  2549                       mode_t mode, bool asset_p, int *fd,
  2550                       AAsset **asset)
  2551 {
  2552   /* Don't allow opening this special directory.  */
  2553   errno = ENOSYS;
  2554   return -1;
  2555 }
  2556 
  2557 static void
  2558 android_content_close (struct android_vnode *vnode)
  2559 {
  2560   int save_errno;
  2561 
  2562   save_errno = errno;
  2563   xfree (vnode);
  2564   errno = save_errno;
  2565 }
  2566 
  2567 static int
  2568 android_content_unlink (struct android_vnode *vnode)
  2569 {
  2570   errno = ENOSYS;
  2571   return -1;
  2572 }
  2573 
  2574 static int
  2575 android_content_symlink (const char *target, struct android_vnode *vnode)
  2576 {
  2577   errno = ENOSYS;
  2578   return -1;
  2579 }
  2580 
  2581 static int
  2582 android_content_rmdir (struct android_vnode *vnode)
  2583 {
  2584   errno = ENOSYS;
  2585   return -1;
  2586 }
  2587 
  2588 static int
  2589 android_content_rename (struct android_vnode *src,
  2590                         struct android_vnode *dst,
  2591                         bool keep_existing)
  2592 {
  2593   if (src->type != dst->type)
  2594     {
  2595       /* If the types of both vnodes differ, complain that they're on
  2596          two different filesystems (which is correct from a abstract
  2597          viewpoint.)  */
  2598       errno = EXDEV;
  2599       return -1;
  2600     }
  2601 
  2602   /* Otherwise, return ENOSYS.  */
  2603   errno = ENOSYS;
  2604   return -1;
  2605 }
  2606 
  2607 static int
  2608 android_content_stat (struct android_vnode *vnode,
  2609                       struct stat *statb)
  2610 {
  2611   memset (statb, 0, sizeof *statb);
  2612 
  2613   statb->st_uid = getuid ();
  2614   statb->st_gid = getgid ();
  2615   statb->st_ino = 0;
  2616   statb->st_dev = -2;
  2617   statb->st_mode = S_IFDIR | S_IRUSR | S_IXUSR;
  2618   return 0;
  2619 }
  2620 
  2621 static int
  2622 android_content_access (struct android_vnode *vnode, int mode)
  2623 {
  2624   /* Validate MODE.  */
  2625 
  2626   if (mode != F_OK && !(mode & (W_OK | X_OK | R_OK)))
  2627     {
  2628       errno = EINVAL;
  2629       return -1;
  2630     }
  2631 
  2632   /* Return EROFS if the caller is trying to check for write access to
  2633      this vnode.  */
  2634 
  2635   if (mode != F_OK && (mode & (W_OK | X_OK)))
  2636     {
  2637       errno = EROFS;
  2638       return -1;
  2639     }
  2640 
  2641   return 0;
  2642 }
  2643 
  2644 static int
  2645 android_content_mkdir (struct android_vnode *vnode, mode_t mode)
  2646 {
  2647   errno = EEXIST;
  2648   return -1;
  2649 }
  2650 
  2651 static int
  2652 android_content_chmod (struct android_vnode *vnode, mode_t mode,
  2653                        int flags)
  2654 {
  2655   errno = EACCES;
  2656   return -1;
  2657 }
  2658 
  2659 static ssize_t
  2660 android_content_readlink (struct android_vnode *vnode, char *buffer,
  2661                           size_t size)
  2662 {
  2663   errno = EINVAL;
  2664   return -1;
  2665 }
  2666 
  2667 static struct dirent *
  2668 android_content_readdir (struct android_vdir *vdir)
  2669 {
  2670   static struct dirent dirent;
  2671   struct android_content_vdir *dir;
  2672   const char *name;
  2673 
  2674   dir = (struct android_content_vdir *) vdir;
  2675 
  2676   /* There are no more files to be read.  */
  2677   if (dir->next_name == (content_directory_contents
  2678                          + ARRAYELTS (content_directory_contents)))
  2679     return NULL;
  2680 
  2681   /* Get the next child.  */
  2682   name = *dir->next_name++;
  2683 
  2684   /* Now, fill in the dirent with the name.  */
  2685   memset (&dirent, 0, sizeof dirent);
  2686   dirent.d_ino = 0;
  2687   dirent.d_off = 0;
  2688   dirent.d_reclen = sizeof dirent;
  2689   dirent.d_type = DT_DIR;
  2690   strcpy (dirent.d_name, name);
  2691   return &dirent;
  2692 }
  2693 
  2694 static void
  2695 android_content_closedir (struct android_vdir *vdir)
  2696 {
  2697   struct android_content_vdir *dir, **next, *tem;
  2698 
  2699   dir = (struct android_content_vdir *) vdir;
  2700 
  2701   /* If the ``directory file descriptor'' has been opened, close
  2702      it.  */
  2703 
  2704   if (dir->fd != -1)
  2705     close (dir->fd);
  2706 
  2707   /* Now unlink this directory.  */
  2708 
  2709   for (next = &all_content_vdirs; (tem = *next);)
  2710     {
  2711       if (tem == dir)
  2712         *next = dir->next;
  2713       else
  2714         next = &(*next)->next;
  2715     }
  2716 
  2717   xfree (dir);
  2718 }
  2719 
  2720 static int
  2721 android_content_dirfd (struct android_vdir *vdir)
  2722 {
  2723   struct android_content_vdir *dir;
  2724 
  2725   dir = (struct android_content_vdir *) vdir;
  2726 
  2727   /* Since `android_content_opendir' tries to avoid opening a file
  2728      descriptor if readdir isn't called, dirfd can fail if open fails.
  2729 
  2730      open sets errno to a set of errors different from what POSIX
  2731      stipulates for dirfd, but for ease of implementation the open
  2732      errors are used instead.  */
  2733 
  2734   if (dir->fd >= 0)
  2735     return dir->fd;
  2736 
  2737   dir->fd = open ("/dev/null", O_RDONLY | O_CLOEXEC);
  2738   return dir->fd;
  2739 }
  2740 
  2741 static struct android_vdir *
  2742 android_content_opendir (struct android_vnode *vnode)
  2743 {
  2744   struct android_content_vdir *dir;
  2745   int api;
  2746 
  2747   /* Allocate the virtual directory.  */
  2748   dir = xmalloc (sizeof *dir);
  2749   dir->vdir.readdir = android_content_readdir;
  2750   dir->vdir.closedir = android_content_closedir;
  2751   dir->vdir.dirfd = android_content_dirfd;
  2752   dir->fd = -1;
  2753 
  2754   /* Fill in the directory contents.  */
  2755   dir->next_name = content_directory_contents;
  2756   api = android_get_current_api_level ();
  2757 
  2758   /* Android 4.4 and earlier don't support /content/storage.  */
  2759 
  2760   if (api < 21)
  2761     dir->next_name++;
  2762 
  2763   /* Android 4.3 and earlier don't support /content/by-authority.  */
  2764 
  2765   if (api < 19)
  2766     dir->next_name++;
  2767 
  2768   /* Link this stream onto the list of all content directory
  2769      streams.  */
  2770   dir->next = all_content_vdirs;
  2771   all_content_vdirs = dir;
  2772   return &dir->vdir;
  2773 }
  2774 
  2775 /* Return the file name corresponding to DIRFD if it is a
  2776    ``directory'' file descriptor returned by `android_content_dirfd'
  2777    or NULL otherwise.  */
  2778 
  2779 static char *
  2780 android_content_get_directory_name (int dirfd)
  2781 {
  2782   struct android_content_vdir *dir;
  2783 
  2784   for (dir = all_content_vdirs; dir; dir = dir->next)
  2785     {
  2786       if (dir->fd == dirfd && dirfd != -1)
  2787         return (char *) "/content";
  2788     }
  2789 
  2790   return NULL;
  2791 }
  2792 
  2793 /* Find the vnode designated by the normalized NAME relative to the
  2794    root of the content file system.  NAME may be modified, and must be
  2795    LENGTH bytes long, excluding its terminating NULL byte.  */
  2796 
  2797 static struct android_vnode *
  2798 android_content_initial (char *name, size_t length)
  2799 {
  2800   struct android_vnode temp;
  2801 
  2802   /* Create a temporary vnode at the root of the asset file
  2803      system.  */
  2804 
  2805   temp.ops = &content_vfs_ops;
  2806   temp.type = ANDROID_VNODE_CONTENT;
  2807   temp.flags = 0;
  2808 
  2809   /* Try to name this vnode.  If NAME is empty, it will be duplicated
  2810      instead.  */
  2811   return android_content_name (&temp, name, length);
  2812 }
  2813 
  2814 
  2815 
  2816 /* Content URI management functions.  */
  2817 
  2818 /* Return the content URI corresponding to a `/content/by-authority'
  2819    file name, or NULL if it is invalid for some reason.  FILENAME
  2820    should be relative to /content/by-authority, with no leading
  2821    directory separator character.  */
  2822 
  2823 static char *
  2824 android_get_content_name (const char *filename)
  2825 {
  2826   char *fill, *buffer;
  2827   size_t length;
  2828 
  2829   /* Make sure FILENAME isn't obviously invalid: it must contain an
  2830      authority name and a file name component.  */
  2831 
  2832   fill = strchr (filename, '/');
  2833   if (!fill || *(fill + 1) == '\0')
  2834     {
  2835       errno = ENOENT;
  2836       return NULL;
  2837     }
  2838 
  2839   /* FILENAME must also not be a directory.  Accessing content
  2840      provider directories is not supported by this interface.  */
  2841 
  2842   length = strlen (filename);
  2843   if (filename[length] == '/')
  2844     {
  2845       errno = ENOTDIR;
  2846       return NULL;
  2847     }
  2848 
  2849   /* Prefix FILENAME with content:// and return the buffer containing
  2850      that URI.  */
  2851 
  2852   buffer = xmalloc (sizeof "content://" + length);
  2853   sprintf (buffer, "content://%s", filename);
  2854   return buffer;
  2855 }
  2856 
  2857 /* Return whether or not the specified URI is an accessible content
  2858    URI.  MODE specifies what to check.
  2859 
  2860    URI must be a string in the JVM's extended UTF-8 format.  */
  2861 
  2862 static bool
  2863 android_check_content_access (const char *uri, int mode)
  2864 {
  2865   jobject string;
  2866   jboolean rc, read, write;
  2867 
  2868   string = (*android_java_env)->NewStringUTF (android_java_env, uri);
  2869   android_exception_check ();
  2870 
  2871   /* Establish what is being checked.  Checking for read access is
  2872      identical to checking if the file exists.  */
  2873 
  2874   read = (bool) (mode & R_OK || (mode == F_OK));
  2875   write = (bool) (mode & W_OK);
  2876 
  2877   rc = (*android_java_env)->CallBooleanMethod (android_java_env,
  2878                                                emacs_service,
  2879                                                service_class.check_content_uri,
  2880                                                string, read, write);
  2881   android_exception_check_1 (string);
  2882   ANDROID_DELETE_LOCAL_REF (string);
  2883   return rc;
  2884 }
  2885 
  2886 
  2887 
  2888 /* Content authority-based vnode implementation.
  2889 
  2890    /contents/by-authority is a simple vnode implementation that converts
  2891    components to content:// URIs.
  2892 
  2893    It does not canonicalize file names by removing parent directory
  2894    separators, as these characters can appear in legitimate content
  2895    file names.  */
  2896 
  2897 struct android_authority_vnode
  2898 {
  2899   /* The vnode data itself.  */
  2900   struct android_vnode vnode;
  2901 
  2902   /* URI associated with this vnode, or NULL if this is the root of
  2903      the content authority tree.  */
  2904   char *uri;
  2905 };
  2906 
  2907 static struct android_vnode *android_authority_name (struct android_vnode *,
  2908                                                      char *, size_t);
  2909 static int android_authority_open (struct android_vnode *, int,
  2910                                    mode_t, bool, int *, AAsset **);
  2911 static void android_authority_close (struct android_vnode *);
  2912 static int android_authority_unlink (struct android_vnode *);
  2913 static int android_authority_symlink (const char *, struct android_vnode *);
  2914 static int android_authority_rmdir (struct android_vnode *);
  2915 static int android_authority_rename (struct android_vnode *,
  2916                                      struct android_vnode *, bool);
  2917 static int android_authority_stat (struct android_vnode *, struct stat *);
  2918 static int android_authority_access (struct android_vnode *, int);
  2919 static int android_authority_mkdir (struct android_vnode *, mode_t);
  2920 static int android_authority_chmod (struct android_vnode *, mode_t, int);
  2921 static ssize_t android_authority_readlink (struct android_vnode *, char *,
  2922                                            size_t);
  2923 static struct android_vdir *android_authority_opendir (struct android_vnode *);
  2924 
  2925 /* Vector of VFS operations associated with the content VFS node.  */
  2926 
  2927 static struct android_vops authority_vfs_ops =
  2928   {
  2929     android_authority_name,
  2930     android_authority_open,
  2931     android_authority_close,
  2932     android_authority_unlink,
  2933     android_authority_symlink,
  2934     android_authority_rmdir,
  2935     android_authority_rename,
  2936     android_authority_stat,
  2937     android_authority_access,
  2938     android_authority_mkdir,
  2939     android_authority_chmod,
  2940     android_authority_readlink,
  2941     android_authority_opendir,
  2942   };
  2943 
  2944 static struct android_vnode *
  2945 android_authority_name (struct android_vnode *vnode, char *name,
  2946                         size_t length)
  2947 {
  2948   struct android_authority_vnode *vp;
  2949   char *uri_name;
  2950 
  2951   if (!android_init_gui)
  2952     {
  2953       errno = EIO;
  2954       return NULL;
  2955     }
  2956 
  2957   /* If NAME is empty or consists of a single directory separator
  2958      _and_ VP->uri is NULL, return a copy of VNODE.  */
  2959 
  2960   vp = (struct android_authority_vnode *) vnode;
  2961 
  2962   if (length < 1 || (*name == '/' && length == 1 && !vp->uri))
  2963     {
  2964       vp = xmalloc (sizeof *vp);
  2965       memcpy (vp, vnode, sizeof *vp);
  2966 
  2967       if (vp->uri)
  2968         vp->uri = xstrdup (vp->uri);
  2969 
  2970       return &vp->vnode;
  2971     }
  2972 
  2973   /* Else, if VP->uri is NULL, then it is the root of the by-authority
  2974      tree.  If NAME starts with a directory separator character,
  2975      remove it.  */
  2976 
  2977   if (!vp->uri)
  2978     {
  2979       if (*name == '/')
  2980         name++, length -= 1;
  2981 
  2982       /* NAME must be a valid JNI string, so that it can be encoded
  2983          properly.  */
  2984 
  2985       if (android_verify_jni_string (name))
  2986         goto no_entry;
  2987 
  2988       uri_name = android_get_content_name (name);
  2989       if (!uri_name)
  2990         goto error;
  2991 
  2992       /* Now fill in the vnode.  */
  2993       vp = xmalloc (sizeof *vp);
  2994       vp->vnode.ops = &authority_vfs_ops;
  2995       vp->vnode.type = ANDROID_VNODE_CONTENT_AUTHORITY;
  2996       vp->vnode.flags = 0;
  2997       vp->uri = uri_name;
  2998       return &vp->vnode;
  2999     }
  3000 
  3001   /* Content files can't have children.  */
  3002  no_entry:
  3003   errno = ENOENT;
  3004  error:
  3005   return NULL;
  3006 }
  3007 
  3008 static int
  3009 android_authority_open (struct android_vnode *vnode, int flags,
  3010                         mode_t mode, bool asset_p, int *fd_return,
  3011                         AAsset **asset)
  3012 {
  3013   struct android_authority_vnode *vp;
  3014   size_t length;
  3015   jobject string;
  3016   int fd;
  3017 
  3018   vp = (struct android_authority_vnode *) vnode;
  3019 
  3020   if (vp->uri == NULL)
  3021     {
  3022       /* This is the `by-authority' directory itself, which can't be
  3023          opened.  */
  3024       errno = ENOSYS;
  3025       return -1;
  3026     }
  3027 
  3028   /* Allocate a buffer to hold the file name.  */
  3029   length = strlen (vp->uri);
  3030   string = (*android_java_env)->NewByteArray (android_java_env,
  3031                                               length);
  3032   if (!string)
  3033     {
  3034       (*android_java_env)->ExceptionClear (android_java_env);
  3035       errno = ENOMEM;
  3036       return -1;
  3037     }
  3038 
  3039   /* Copy the URI into this byte array.  */
  3040   (*android_java_env)->SetByteArrayRegion (android_java_env,
  3041                                            string, 0, length,
  3042                                            (jbyte *) vp->uri);
  3043 
  3044   /* Try to open the file descriptor.  */
  3045 
  3046   fd
  3047     = (*android_java_env)->CallIntMethod (android_java_env,
  3048                                           emacs_service,
  3049                                           service_class.open_content_uri,
  3050                                           string,
  3051                                           (jboolean) ((mode & O_WRONLY
  3052                                                        || mode & O_RDWR)
  3053                                                       != 0),
  3054                                           (jboolean) !(mode & O_WRONLY),
  3055                                           (jboolean) ((mode & O_TRUNC)
  3056                                                       != 0));
  3057 
  3058   if ((*android_java_env)->ExceptionCheck (android_java_env))
  3059     {
  3060       (*android_java_env)->ExceptionClear (android_java_env);
  3061       errno = ENOMEM;
  3062       ANDROID_DELETE_LOCAL_REF (string);
  3063       return -1;
  3064     }
  3065 
  3066   /* If fd is -1, just assume that the file does not exist,
  3067      and return -1 with errno set to ENOENT.  */
  3068 
  3069   if (fd == -1)
  3070     {
  3071       errno = ENOENT;
  3072       goto skip;
  3073     }
  3074 
  3075   if (mode & O_CLOEXEC)
  3076     android_close_on_exec (fd);
  3077 
  3078  skip:
  3079   ANDROID_DELETE_LOCAL_REF (string);
  3080 
  3081   if (fd == -1)
  3082     return -1;
  3083 
  3084   *fd_return = fd;
  3085   return 0;
  3086 }
  3087 
  3088 static void
  3089 android_authority_close (struct android_vnode *vnode)
  3090 {
  3091   struct android_authority_vnode *vp;
  3092   int save_errno;
  3093 
  3094   vp = (struct android_authority_vnode *) vnode;
  3095   save_errno = errno;
  3096   xfree (vp->uri);
  3097   xfree (vp);
  3098   errno = save_errno;
  3099 }
  3100 
  3101 static int
  3102 android_authority_unlink (struct android_vnode *vnode)
  3103 {
  3104   errno = EROFS;
  3105   return -1;
  3106 }
  3107 
  3108 static int
  3109 android_authority_symlink (const char *target,
  3110                            struct android_vnode *vnode)
  3111 {
  3112   errno = EROFS;
  3113   return -1;
  3114 }
  3115 
  3116 static int
  3117 android_authority_rmdir (struct android_vnode *vnode)
  3118 {
  3119   errno = EROFS;
  3120   return -1;
  3121 }
  3122 
  3123 static int
  3124 android_authority_rename (struct android_vnode *src,
  3125                           struct android_vnode *dst,
  3126                           bool keep_existing)
  3127 {
  3128   if (src->type != dst->type)
  3129     {
  3130       /* If the types of both vnodes differ, complain that they're on
  3131          two different filesystems (which is correct from a abstract
  3132          viewpoint.)  */
  3133       errno = EXDEV;
  3134       return -1;
  3135     }
  3136 
  3137   /* Otherwise, return ENOSYS.  */
  3138   errno = ENOSYS;
  3139   return -1;
  3140 }
  3141 
  3142 static int
  3143 android_authority_stat (struct android_vnode *vnode,
  3144                         struct stat *statb)
  3145 {
  3146   int rc, fd, save_errno;
  3147   struct android_authority_vnode *vp;
  3148 
  3149   /* If this is a vnode representing `by-authority', return some
  3150      information about this directory.  */
  3151 
  3152   vp = (struct android_authority_vnode *) vnode;
  3153 
  3154   if (!vp->uri)
  3155     {
  3156       memset (statb, 0, sizeof *statb);
  3157       statb->st_uid = getuid ();
  3158       statb->st_gid = getgid ();
  3159       statb->st_ino = 0;
  3160       statb->st_dev = -3;
  3161       statb->st_mode = S_IFDIR | S_IRUSR;
  3162       return 0;
  3163     }
  3164 
  3165   /* Try to open the file and call fstat.  */
  3166   rc = (*vnode->ops->open) (vnode, O_RDONLY, 0, false, &fd, NULL);
  3167 
  3168   if (rc < 0)
  3169     return -1;
  3170 
  3171   /* If rc is 1, then an asset file descriptor has been returned.
  3172      This is impossible, so assert that it doesn't transpire.  */
  3173   assert (rc != 1);
  3174 
  3175   /* Now, try to stat the file.  */
  3176   rc = fstat (fd, statb);
  3177   save_errno = errno;
  3178 
  3179   /* Close the file descriptor.  */
  3180   close (fd);
  3181 
  3182   /* Restore errno.  */
  3183   errno = save_errno;
  3184   return rc;
  3185 }
  3186 
  3187 static int
  3188 android_authority_access (struct android_vnode *vnode, int mode)
  3189 {
  3190   struct android_authority_vnode *vp;
  3191 
  3192   vp = (struct android_authority_vnode *) vnode;
  3193 
  3194   /* Validate MODE.  */
  3195 
  3196   if (mode != F_OK && !(mode & (W_OK | X_OK | R_OK)))
  3197     {
  3198       errno = EINVAL;
  3199       return -1;
  3200     }
  3201 
  3202   if (!vp->uri)
  3203     {
  3204       /* Return EACCES if the caller is trying to check for write
  3205          access to `by-authority'.  */
  3206 
  3207       if (mode != F_OK && (mode & (W_OK | X_OK)))
  3208         {
  3209           errno = EACCES;
  3210           return -1;
  3211         }
  3212 
  3213       return 0;
  3214     }
  3215 
  3216   return (android_check_content_access (vp->uri, mode)
  3217           ? 0 : -1);
  3218 }
  3219 
  3220 static int
  3221 android_authority_mkdir (struct android_vnode *vnode, mode_t mode)
  3222 {
  3223   errno = EACCES;
  3224   return -1;
  3225 }
  3226 
  3227 static int
  3228 android_authority_chmod (struct android_vnode *vnode, mode_t mode,
  3229                          int flags)
  3230 {
  3231   errno = EACCES;
  3232   return -1;
  3233 }
  3234 
  3235 static ssize_t
  3236 android_authority_readlink (struct android_vnode *vnode, char *buffer,
  3237                             size_t size)
  3238 {
  3239   errno = EINVAL;
  3240   return -1;
  3241 }
  3242 
  3243 static struct android_vdir *
  3244 android_authority_opendir (struct android_vnode *vnode)
  3245 {
  3246   struct android_authority_vnode *vp;
  3247 
  3248   /* Forbid listing the `by-authority' directory.  */
  3249   vp = (struct android_authority_vnode *) vnode;
  3250   errno = vp->uri ? ENOTDIR : EACCES;
  3251   return NULL;
  3252 }
  3253 
  3254 /* Find the vnode designated by NAME relative to the root of the
  3255    by-authority directory.
  3256 
  3257    If NAME is empty or a single leading separator character, return
  3258    a vnode representing the by-authority directory itself.
  3259 
  3260    Otherwise, represent the remainder of NAME as a URI (without
  3261    normalizing it) and return a vnode corresponding to that.
  3262 
  3263    Value may also be NULL with errno set if the designated vnode is
  3264    not available, such as when Android windowing has not been
  3265    initialized.  */
  3266 
  3267 static struct android_vnode *
  3268 android_authority_initial (char *name, size_t length)
  3269 {
  3270   struct android_authority_vnode temp;
  3271 
  3272   temp.vnode.ops = &authority_vfs_ops;
  3273   temp.vnode.type = ANDROID_VNODE_CONTENT_AUTHORITY;
  3274   temp.vnode.flags = 0;
  3275   temp.uri = NULL;
  3276 
  3277   return android_authority_name (&temp.vnode, name, length);
  3278 }
  3279 
  3280 
  3281 
  3282 /* SAF ``root'' vnode implementation.
  3283 
  3284    The Storage Access Framework is a system service that manages a
  3285    registry of document providers, which are a type of file system
  3286    server.
  3287 
  3288    Normally, document providers can only provide individual files
  3289    through preestablished ``content URIs''.  Android 5.0 and later add
  3290    to that ``tree URIs'', which designate entire file system trees.
  3291 
  3292    Authorization to access document trees and content URIs is granted
  3293    transiently by default when an Intent is received, but Emacs can
  3294    also receive persistent authorization for a given document tree.
  3295 
  3296    /content/storage returns a list of directories, each representing a
  3297    single authority providing at least one tree URI Emacs holds
  3298    persistent authorization for.
  3299 
  3300    Each one of those directories then contains one document tree that
  3301    Emacs is authorized to access.  */
  3302 
  3303 struct android_saf_root_vnode
  3304 {
  3305   /* The vnode data.  */
  3306   struct android_vnode vnode;
  3307 
  3308   /* The name of the document authority this directory represents, or
  3309      NULL.  */
  3310   char *authority;
  3311 };
  3312 
  3313 struct android_saf_root_vdir
  3314 {
  3315   /* The directory stream function table.  */
  3316   struct android_vdir vdir;
  3317 
  3318   /* The next directory stream in `all_saf_root_vdirs'.  */
  3319   struct android_saf_root_vdir *next;
  3320 
  3321   /* Array of strings, one for each directory to return.  */
  3322   jobjectArray array;
  3323 
  3324   /* Name of the authority this directory lists, or NULL.  */
  3325   char *authority;
  3326 
  3327   /* Length of that array, and the current within it.  */
  3328   jsize length, i;
  3329 
  3330   /* ``Directory'' file descriptor associated with this stream, or
  3331      -1.  */
  3332   int fd;
  3333 };
  3334 
  3335 static struct android_vnode *android_saf_root_name (struct android_vnode *,
  3336                                                     char *, size_t);
  3337 static int android_saf_root_open (struct android_vnode *, int,
  3338                                   mode_t, bool, int *, AAsset **);
  3339 static void android_saf_root_close (struct android_vnode *);
  3340 static int android_saf_root_unlink (struct android_vnode *);
  3341 static int android_saf_root_symlink (const char *, struct android_vnode *);
  3342 static int android_saf_root_rmdir (struct android_vnode *);
  3343 static int android_saf_root_rename (struct android_vnode *,
  3344                                     struct android_vnode *, bool);
  3345 static int android_saf_root_stat (struct android_vnode *, struct stat *);
  3346 static int android_saf_root_access (struct android_vnode *, int);
  3347 static int android_saf_root_mkdir (struct android_vnode *, mode_t);
  3348 static int android_saf_root_chmod (struct android_vnode *, mode_t, int);
  3349 static ssize_t android_saf_root_readlink (struct android_vnode *, char *,
  3350                                           size_t);
  3351 static struct android_vdir *android_saf_root_opendir (struct android_vnode *);
  3352 
  3353 /* Vector of VFS operations associated with the SAF root VFS node.  */
  3354 
  3355 static struct android_vops saf_root_vfs_ops =
  3356   {
  3357     android_saf_root_name,
  3358     android_saf_root_open,
  3359     android_saf_root_close,
  3360     android_saf_root_unlink,
  3361     android_saf_root_symlink,
  3362     android_saf_root_rmdir,
  3363     android_saf_root_rename,
  3364     android_saf_root_stat,
  3365     android_saf_root_access,
  3366     android_saf_root_mkdir,
  3367     android_saf_root_chmod,
  3368     android_saf_root_readlink,
  3369     android_saf_root_opendir,
  3370   };
  3371 
  3372 /* Chain containing all SAF root directories.  */
  3373 static struct android_saf_root_vdir *all_saf_root_vdirs;
  3374 
  3375 /* Defined in the next page.  */
  3376 static struct android_vnode *android_saf_tree_from_name (char *, const char *,
  3377                                                          const char *);
  3378 
  3379 /* Ascertain and return whether or not AUTHORITY designates a content
  3380    provider offering at least one directory tree accessible to
  3381    Emacs.  */
  3382 
  3383 static bool
  3384 android_saf_valid_authority_p (const char *authority)
  3385 {
  3386   jobject string;
  3387   jboolean valid;
  3388   jmethodID method;
  3389 
  3390   /* Make certain AUTHORITY can actually be represented as a Java
  3391      string.  */
  3392 
  3393   if (android_verify_jni_string (authority))
  3394     return false;
  3395 
  3396   /* Build a string containing AUTHORITY.  */
  3397 
  3398   string = (*android_java_env)->NewStringUTF (android_java_env,
  3399                                               authority);
  3400   android_exception_check ();
  3401 
  3402   method = service_class.valid_authority;
  3403   valid
  3404     = (*android_java_env)->CallNonvirtualBooleanMethod (android_java_env,
  3405                                                         emacs_service,
  3406                                                         service_class.class,
  3407                                                         method, string);
  3408   android_exception_check_1 (string);
  3409   ANDROID_DELETE_LOCAL_REF (string);
  3410   return valid;
  3411 }
  3412 
  3413 static struct android_vnode *
  3414 android_saf_root_name (struct android_vnode *vnode, char *name,
  3415                        size_t length)
  3416 {
  3417   char *remainder, *component_end;
  3418   struct android_saf_root_vnode *vp;
  3419   struct android_vnode *new;
  3420   char component[PATH_MAX];
  3421 
  3422   /* Canonicalize NAME.  */
  3423   remainder = android_vfs_canonicalize_name (name, &length);
  3424 
  3425   /* If remainder is set, it's a name relative to the root vnode.  */
  3426   if (remainder)
  3427     goto parent_vnode;
  3428 
  3429   /* If LENGTH is empty or NAME is a single directory separator,
  3430      return a copy of this vnode.  */
  3431 
  3432   if (length < 1 || (*name == '/' && length == 1))
  3433     {
  3434       vp = xmalloc (sizeof *vp);
  3435       memcpy (vp, vnode, sizeof *vp);
  3436 
  3437       if (vp->authority)
  3438         vp->authority = xstrdup (vp->authority);
  3439 
  3440       return &vp->vnode;
  3441     }
  3442 
  3443   vp = (struct android_saf_root_vnode *) vnode;
  3444 
  3445   /* If NAME starts with a directory separator, move it past that.  */
  3446 
  3447   if (*name == '/')
  3448     name++, length -= 1;
  3449 
  3450   /* Look for the first directory separator.  */
  3451   component_end = strchr (name, '/');
  3452 
  3453   /* If not there, use name + length.  */
  3454 
  3455   if (!component_end)
  3456     component_end = name + length;
  3457 
  3458   if (component_end - name >= PATH_MAX)
  3459     {
  3460       errno = ENAMETOOLONG;
  3461       return NULL;
  3462     }
  3463 
  3464   /* Copy the component over.  */
  3465   memcpy (component, name, component_end - name);
  3466   component[component_end - name] = '\0';
  3467 
  3468   /* Create a SAF document vnode for this tree if it represents an
  3469      authority.  */
  3470 
  3471   if (vp->authority)
  3472     return android_saf_tree_from_name (component_end, component,
  3473                                        vp->authority);
  3474 
  3475   /* Create the vnode.  */
  3476   vp = xmalloc (sizeof *vp);
  3477   vp->vnode.ops = &saf_root_vfs_ops;
  3478   vp->vnode.type = ANDROID_VNODE_SAF_ROOT;
  3479   vp->vnode.flags = 0;
  3480   vp->authority = xstrdup (component);
  3481 
  3482   /* If there is more of this component to be named, name it through
  3483      the new vnode.  */
  3484 
  3485   if (component_end != name + length)
  3486     {
  3487       new = (*vp->vnode.ops->name) (&vp->vnode, component_end,
  3488                                     length - (component_end - name));
  3489       (*vp->vnode.ops->close) (&vp->vnode);
  3490 
  3491       return new;
  3492     }
  3493 
  3494   return &vp->vnode;
  3495 
  3496  parent_vnode:
  3497   vp = (struct android_saf_root_vnode *) vnode;
  3498 
  3499   /* .. was encountered and the parent couldn't be found through
  3500      stripping off preceding components.
  3501 
  3502      Find the parent vnode and name the rest of NAME starting from
  3503      there.  */
  3504 
  3505   if (!vp->authority)
  3506     /* Look this file name up relative to the root of the contents
  3507        directory.  */
  3508     return android_content_initial (remainder, strlen (remainder));
  3509   else
  3510     /* Look this file name up relative to the root of the storage
  3511        directory.  */
  3512     return android_saf_root_initial (remainder, strlen (remainder));
  3513 }
  3514 
  3515 static int
  3516 android_saf_root_open (struct android_vnode *vnode, int flags,
  3517                        mode_t mode, bool asset_p, int *fd_return,
  3518                        AAsset **asset)
  3519 {
  3520   /* /content/storage or one of its authority children cannot be
  3521      opened, as they are virtual directories.  */
  3522 
  3523   errno = ENOSYS;
  3524   return -1;
  3525 }
  3526 
  3527 static void
  3528 android_saf_root_close (struct android_vnode *vnode)
  3529 {
  3530   struct android_saf_root_vnode *vp;
  3531   int save_errno;
  3532 
  3533   vp = (struct android_saf_root_vnode *) vnode;
  3534   save_errno = errno;
  3535   xfree (vp->authority);
  3536   xfree (vp);
  3537   errno = save_errno;
  3538 }
  3539 
  3540 static int
  3541 android_saf_root_unlink (struct android_vnode *vnode)
  3542 {
  3543   errno = EROFS;
  3544   return -1;
  3545 }
  3546 
  3547 static int
  3548 android_saf_root_symlink (const char *target,
  3549                           struct android_vnode *vnode)
  3550 {
  3551   errno = EROFS;
  3552   return -1;
  3553 }
  3554 
  3555 static int
  3556 android_saf_root_rmdir (struct android_vnode *vnode)
  3557 {
  3558   errno = EROFS;
  3559   return -1;
  3560 }
  3561 
  3562 static int
  3563 android_saf_root_rename (struct android_vnode *src,
  3564                          struct android_vnode *dst,
  3565                          bool keep_existing)
  3566 {
  3567   errno = EROFS;
  3568   return -1;
  3569 }
  3570 
  3571 static int
  3572 android_saf_root_stat (struct android_vnode *vnode,
  3573                        struct stat *statb)
  3574 {
  3575   struct android_saf_root_vnode *vp;
  3576 
  3577   /* Verify that the authority actually exists and return ENOENT
  3578      otherwise, lest `locate-dominating-file' & co call an operation
  3579      that doesn't require listing URIs under this authority, such as
  3580      access.  */
  3581 
  3582   vp = (struct android_saf_root_vnode *) vnode;
  3583 
  3584   if (vp->authority
  3585       && !android_saf_valid_authority_p (vp->authority))
  3586     {
  3587       errno = ENOENT;
  3588       return -1;
  3589     }
  3590 
  3591   /* Make up some imaginary statistics for this vnode.  */
  3592 
  3593   memset (statb, 0, sizeof *statb);
  3594   statb->st_uid = getuid ();
  3595   statb->st_gid = getgid ();
  3596   statb->st_ino = 0;
  3597   statb->st_dev = -4;
  3598   statb->st_mode = S_IFDIR | S_IRUSR | S_IXUSR;
  3599   return 0;
  3600 }
  3601 
  3602 static int
  3603 android_saf_root_access (struct android_vnode *vnode, int mode)
  3604 {
  3605   struct android_saf_root_vnode *vp;
  3606 
  3607   /* Validate MODE.  */
  3608 
  3609   if (mode != F_OK && !(mode & (W_OK | X_OK | R_OK)))
  3610     {
  3611       errno = EINVAL;
  3612       return -1;
  3613     }
  3614 
  3615   /* Now, don't allow writing or executing this directory.  */
  3616 
  3617   if (mode != F_OK && (mode & (W_OK | X_OK)))
  3618     {
  3619       errno = EROFS;
  3620       return -1;
  3621     }
  3622 
  3623   /* Verify that the authority actually exists and return ENOENT
  3624      otherwise, lest `locate-dominating-file' & co call an operation
  3625      that doesn't require listing URIs under this authority, such as
  3626      access.  */
  3627 
  3628   vp = (struct android_saf_root_vnode *) vnode;
  3629 
  3630   if (vp->authority
  3631       && !android_saf_valid_authority_p (vp->authority))
  3632     {
  3633       errno = ENOENT;
  3634       return -1;
  3635     }
  3636 
  3637   return 0;
  3638 }
  3639 
  3640 static int
  3641 android_saf_root_mkdir (struct android_vnode *vnode, mode_t mode)
  3642 {
  3643   errno = EROFS;
  3644   return -1;
  3645 }
  3646 
  3647 static int
  3648 android_saf_root_chmod (struct android_vnode *vnode, mode_t mode,
  3649                         int flags)
  3650 {
  3651   errno = EACCES;
  3652   return -1;
  3653 }
  3654 
  3655 static ssize_t
  3656 android_saf_root_readlink (struct android_vnode *vnode, char *buffer,
  3657                            size_t size)
  3658 {
  3659   errno = EINVAL;
  3660   return -1;
  3661 }
  3662 
  3663 static struct dirent *
  3664 android_saf_root_readdir (struct android_vdir *vdir)
  3665 {
  3666   static struct dirent *dirent;
  3667   jobject string;
  3668   const char *chars;
  3669   size_t length, size;
  3670   struct android_saf_root_vdir *dir;
  3671 
  3672   dir = (struct android_saf_root_vdir *) vdir;
  3673 
  3674   if (dir->i == dir->length)
  3675     {
  3676       /* At the end of the stream.  Free dirent and return NULL.  */
  3677 
  3678       xfree (dirent);
  3679       dirent = NULL;
  3680       return NULL;
  3681     }
  3682 
  3683   /* Get this string.  */
  3684   string = (*android_java_env)->GetObjectArrayElement (android_java_env,
  3685                                                        dir->array, dir->i++);
  3686   android_exception_check ();
  3687   chars = (*android_java_env)->GetStringUTFChars (android_java_env,
  3688                                                   (jstring) string,
  3689                                                   NULL);
  3690   android_exception_check_nonnull ((void *) chars, string);
  3691 
  3692   /* Figure out how large it is, and then resize dirent to fit.  */
  3693   length = strlen (chars) + 1;
  3694   size   = offsetof (struct dirent, d_name) + length;
  3695   dirent = xrealloc (dirent, size);
  3696 
  3697   /* Clear dirent.  */
  3698   memset (dirent, 0, size);
  3699 
  3700   /* Fill in the generic directory information and copy the string
  3701      over.  */
  3702   dirent->d_ino = 0;
  3703   dirent->d_off = 0;
  3704   dirent->d_reclen = size;
  3705   dirent->d_type = DT_DIR;
  3706   strcpy (dirent->d_name, chars);
  3707 
  3708   /* Release the string data and the local reference to STRING.  */
  3709   (*android_java_env)->ReleaseStringUTFChars (android_java_env,
  3710                                               (jstring) string, chars);
  3711   ANDROID_DELETE_LOCAL_REF (string);
  3712   return dirent;
  3713 }
  3714 
  3715 static void
  3716 android_saf_root_closedir (struct android_vdir *vdir)
  3717 {
  3718   struct android_saf_root_vdir *dir, **next, *tem;
  3719 
  3720   dir = (struct android_saf_root_vdir *) vdir;
  3721 
  3722   /* If the ``directory file descriptor'' has been opened, close
  3723      it.  */
  3724 
  3725   if (dir->fd != -1)
  3726     close (dir->fd);
  3727 
  3728   /* Delete the local reference to the file name array.  */
  3729   ANDROID_DELETE_LOCAL_REF (dir->array);
  3730 
  3731   /* Free the authority name if set.  */
  3732   xfree (dir->authority);
  3733 
  3734   /* Now unlink this directory.  */
  3735 
  3736   for (next = &all_saf_root_vdirs; (tem = *next);)
  3737     {
  3738       if (tem == dir)
  3739         *next = dir->next;
  3740       else
  3741         next = &(*next)->next;
  3742     }
  3743 
  3744   /* Free the directory itself.  */
  3745   xfree (dir);
  3746 }
  3747 
  3748 static int
  3749 android_saf_root_dirfd (struct android_vdir *vdir)
  3750 {
  3751   struct android_saf_root_vdir *dir;
  3752 
  3753   dir = (struct android_saf_root_vdir *) vdir;
  3754 
  3755   /* Since `android_saf_root_opendir' tries to avoid opening a file
  3756      descriptor if readdir isn't called, dirfd can fail if open fails.
  3757 
  3758      open sets errno to a set of errors different from what POSIX
  3759      stipulates for dirfd, but for ease of implementation the open
  3760      errors are used instead.  */
  3761 
  3762   if (dir->fd >= 0)
  3763     return dir->fd;
  3764 
  3765   dir->fd = open ("/dev/null", O_RDONLY | O_CLOEXEC);
  3766   return dir->fd;
  3767 }
  3768 
  3769 static struct android_vdir *
  3770 android_saf_root_opendir (struct android_vnode *vnode)
  3771 {
  3772   struct android_saf_root_vnode *vp;
  3773   jobjectArray array;
  3774   jmethodID method;
  3775   jbyteArray authority;
  3776   struct android_saf_root_vdir *dir;
  3777   size_t length;
  3778 
  3779   vp = (struct android_saf_root_vnode *) vnode;
  3780 
  3781   if (vp->authority)
  3782     {
  3783       /* Build a string containing the authority.  */
  3784       length = strlen (vp->authority);
  3785       authority = (*android_java_env)->NewByteArray (android_java_env,
  3786                                                      length);
  3787       android_exception_check ();
  3788 
  3789       /* Copy the authority name to that byte array.  */
  3790       (*android_java_env)->SetByteArrayRegion (android_java_env,
  3791                                                authority, 0, length,
  3792                                                (jbyte *) vp->authority);
  3793 
  3794       /* Acquire a list of every tree provided by this authority.  */
  3795 
  3796       method = service_class.get_document_trees;
  3797       array
  3798         = (*android_java_env)->CallNonvirtualObjectMethod (android_java_env,
  3799                                                            emacs_service,
  3800                                                            service_class.class,
  3801                                                            method, authority);
  3802       android_exception_check_1 (authority);
  3803       ANDROID_DELETE_LOCAL_REF (authority);
  3804 
  3805       /* Ascertain the length of the array.  If it is empty or NULL,
  3806          return ENOENT.  */
  3807 
  3808       if (!array)
  3809         {
  3810           errno = ENOENT;
  3811           return NULL;
  3812         }
  3813 
  3814       length = (*android_java_env)->GetArrayLength (android_java_env, array);
  3815 
  3816       if (!length)
  3817         {
  3818           ANDROID_DELETE_LOCAL_REF (array);
  3819           errno = ENOENT;
  3820           return NULL;
  3821         }
  3822 
  3823       /* Now allocate the directory stream.  It will retain a local
  3824          reference to the array, and should thus only be used within the
  3825          same JNI local reference frame.  */
  3826 
  3827       dir = xmalloc (sizeof *dir);
  3828       dir->vdir.readdir = android_saf_root_readdir;
  3829       dir->vdir.closedir = android_saf_root_closedir;
  3830       dir->vdir.dirfd = android_saf_root_dirfd;
  3831       dir->fd = -1;
  3832       dir->array = array;
  3833       dir->length = length;
  3834       dir->i = 0;
  3835       dir->authority = xstrdup (vp->authority);
  3836 
  3837       /* Link this stream onto the list of all SAF root directory
  3838          streams.  */
  3839       dir->next = all_saf_root_vdirs;
  3840       all_saf_root_vdirs = dir;
  3841       return &dir->vdir;
  3842     }
  3843 
  3844   /* Acquire a list of every document authority.  */
  3845 
  3846   method = service_class.get_document_authorities;
  3847   array = (*android_java_env)->CallNonvirtualObjectMethod (android_java_env,
  3848                                                            emacs_service,
  3849                                                            service_class.class,
  3850                                                            method);
  3851   android_exception_check ();
  3852 
  3853   if (!array)
  3854     emacs_abort ();
  3855 
  3856   /* Now allocate the directory stream.  It will retain a local
  3857      reference to the array, and should thus only be used within the
  3858      same JNI local reference frame.  */
  3859 
  3860   dir = xmalloc (sizeof *dir);
  3861   dir->vdir.readdir = android_saf_root_readdir;
  3862   dir->vdir.closedir = android_saf_root_closedir;
  3863   dir->vdir.dirfd = android_saf_root_dirfd;
  3864   dir->fd = -1;
  3865   dir->array = array;
  3866   dir->length = (*android_java_env)->GetArrayLength (android_java_env,
  3867                                                      array);
  3868   dir->i = 0;
  3869   dir->authority = NULL;
  3870 
  3871   /* Link this stream onto the list of all SAF root directory
  3872      streams.  */
  3873   dir->next = all_saf_root_vdirs;
  3874   all_saf_root_vdirs = dir;
  3875   return &dir->vdir;
  3876 }
  3877 
  3878 /* Find the vnode designated by NAME relative to the root of the
  3879    storage directory.
  3880 
  3881    If NAME is empty or a single leading separator character, return a
  3882    vnode representing the storage directory itself.
  3883 
  3884    If NAME actually resides in a parent directory, look for it within
  3885    the vnode representing the content directory.  */
  3886 
  3887 static struct android_vnode *
  3888 android_saf_root_initial (char *name, size_t length)
  3889 {
  3890   struct android_saf_root_vnode temp;
  3891 
  3892   temp.vnode.ops = &saf_root_vfs_ops;
  3893   temp.vnode.type = ANDROID_VNODE_SAF_ROOT;
  3894   temp.vnode.flags = 0;
  3895   temp.authority = NULL;
  3896 
  3897   return android_saf_root_name (&temp.vnode, name, length);
  3898 }
  3899 
  3900 /* Return any open SAF root directory stream for which dirfd has
  3901    returned the file descriptor DIRFD.  Return NULL otherwise.  */
  3902 
  3903 static struct android_saf_root_vdir *
  3904 android_saf_root_get_directory (int dirfd)
  3905 {
  3906   struct android_saf_root_vdir *dir;
  3907 
  3908   for (dir = all_saf_root_vdirs; dir; dir = dir->next)
  3909     {
  3910       if (dir->fd == dirfd && dirfd != -1)
  3911         return dir;
  3912     }
  3913 
  3914   return NULL;
  3915 }
  3916 
  3917 
  3918 
  3919 /* Functions common to both SAF directory and file nodes.  */
  3920 
  3921 /* Whether or not Emacs is within an operation running from the SAF
  3922    thread.  */
  3923 static bool inside_saf_critical_section;
  3924 
  3925 /* Check for JNI exceptions, clear them, and set errno accordingly.
  3926    Also, free each of the N local references given as arguments if an
  3927    exception takes place.
  3928 
  3929    Value is 1 if an exception has taken place, 0 otherwise.
  3930 
  3931    If the exception thrown derives from FileNotFoundException, set
  3932    errno to ENOENT.
  3933 
  3934    If the exception thrown derives from SecurityException, set errno
  3935    to EACCES.
  3936 
  3937    If the exception thrown derives from OperationCanceledException,
  3938    set errno to EINTR.
  3939 
  3940    If the exception thrown derives from UnsupportedOperationException,
  3941    set errno to ENOSYS.
  3942 
  3943    If the exception thrown derives from OutOfMemoryException, call
  3944    `memory_full'.
  3945 
  3946    If the exception thrown is anything else, set errno to EIO.  */
  3947 
  3948 static int
  3949 android_saf_exception_check (int n, ...)
  3950 {
  3951   jthrowable exception;
  3952   JNIEnv *env;
  3953   va_list ap;
  3954   int new_errno;
  3955 
  3956   env = android_java_env;
  3957   va_start (ap, n);
  3958 
  3959   /* First, check for an exception.  */
  3960 
  3961   if (!(*env)->ExceptionCheck (env))
  3962     /* No exception has taken place.  Return 0.  */
  3963     return 0;
  3964 
  3965   /* Print the exception.  */
  3966   (*env)->ExceptionDescribe (env);
  3967 
  3968   exception = (*env)->ExceptionOccurred (env);
  3969 
  3970   if (!exception)
  3971     /* JNI couldn't return a local reference to the exception.  */
  3972     memory_full (0);
  3973 
  3974   /* Clear the exception, making it safe to subsequently call other
  3975      JNI functions.  */
  3976   (*env)->ExceptionClear (env);
  3977 
  3978   /* Delete each of the N arguments.  */
  3979 
  3980   while (n > 0)
  3981     {
  3982       ANDROID_DELETE_LOCAL_REF (va_arg (ap, jobject));
  3983       n--;
  3984     }
  3985 
  3986   /* Now set errno or signal memory_full as required.  */
  3987 
  3988   if ((*env)->IsInstanceOf (env, (jobject) exception,
  3989                             file_not_found_exception))
  3990     new_errno = ENOENT;
  3991   else if ((*env)->IsInstanceOf (env, (jobject) exception,
  3992                                  security_exception))
  3993     new_errno = EACCES;
  3994   else if ((*env)->IsInstanceOf (env, (jobject) exception,
  3995                                  operation_canceled_exception))
  3996     new_errno = EINTR;
  3997   else if ((*env)->IsInstanceOf (env, (jobject) exception,
  3998                                  unsupported_operation_exception))
  3999     new_errno = ENOSYS;
  4000   else if ((*env)->IsInstanceOf (env, (jobject) exception,
  4001                                  out_of_memory_error))
  4002     {
  4003       ANDROID_DELETE_LOCAL_REF ((jobject) exception);
  4004       memory_full (0);
  4005     }
  4006   else
  4007     new_errno = EIO;
  4008 
  4009   /* expression is still a local reference! */
  4010   ANDROID_DELETE_LOCAL_REF ((jobject) exception);
  4011   errno = new_errno;
  4012   return 1;
  4013 }
  4014 
  4015 /* Return file status for the document designated by ID_NAME within
  4016    the document tree identified by URI_NAME.
  4017 
  4018    If NO_CACHE, don't cache the resulting file status.  Enable this
  4019    option if the file status is subject to imminent change.
  4020 
  4021    If the file status is available, place it within *STATB and return
  4022    0.  If not, return -1 and set errno to EPERM.  */
  4023 
  4024 static int
  4025 android_saf_stat (const char *uri_name, const char *id_name,
  4026                   struct stat *statb, bool no_cache)
  4027 {
  4028   jmethodID method;
  4029   jstring uri, id;
  4030   jobject status;
  4031   jlong mode, size, mtim, *longs;
  4032 
  4033   /* Now guarantee that it is safe to call functions which
  4034      synchronize with the SAF thread.  */
  4035 
  4036   if (inside_saf_critical_section)
  4037     {
  4038       errno = EIO;
  4039       return -1;
  4040     }
  4041 
  4042   /* Build strings for both URI and ID.  */
  4043   uri = (*android_java_env)->NewStringUTF (android_java_env, uri_name);
  4044   android_exception_check ();
  4045 
  4046   if (id_name)
  4047     {
  4048       id = (*android_java_env)->NewStringUTF (android_java_env,
  4049                                               id_name);
  4050       android_exception_check_1 (uri);
  4051     }
  4052   else
  4053     id = NULL;
  4054 
  4055   /* Try to retrieve the file status.  */
  4056   method = service_class.stat_document;
  4057   inside_saf_critical_section = true;
  4058   status
  4059     = (*android_java_env)->CallNonvirtualObjectMethod (android_java_env,
  4060                                                        emacs_service,
  4061                                                        service_class.class,
  4062                                                        method, uri, id,
  4063                                                        (jboolean) no_cache);
  4064   inside_saf_critical_section = false;
  4065 
  4066   /* Check for exceptions and release unneeded local references.  */
  4067 
  4068   if (id)
  4069     {
  4070       if (android_saf_exception_check (2, uri, id))
  4071         return -1;
  4072 
  4073       ANDROID_DELETE_LOCAL_REF (id);
  4074     }
  4075   else if (android_saf_exception_check (1, uri))
  4076     return -1;
  4077 
  4078   ANDROID_DELETE_LOCAL_REF (uri);
  4079 
  4080   /* Check for failure.  */
  4081 
  4082   if (!status)
  4083     {
  4084       errno = EPERM;
  4085       return -1;
  4086     }
  4087 
  4088   /* Read the file status from the array returned.  */
  4089 
  4090   longs = (*android_java_env)->GetLongArrayElements (android_java_env,
  4091                                                      status, NULL);
  4092   android_exception_check_nonnull (longs, status);
  4093   mode = longs[0];
  4094   size = longs[1];
  4095   mtim = longs[2];
  4096   (*android_java_env)->ReleaseLongArrayElements (android_java_env, status,
  4097                                                  longs, JNI_ABORT);
  4098   ANDROID_DELETE_LOCAL_REF (status);
  4099 
  4100   /* Fill in STATB with this information.  */
  4101   memset (statb, 0, sizeof *statb);
  4102   statb->st_size = MAX (0, MIN (TYPE_MAXIMUM (off_t), size));
  4103   statb->st_mode = mode;
  4104   statb->st_dev = -4;
  4105 #ifdef STAT_TIMESPEC
  4106   STAT_TIMESPEC (statb, st_mtim).tv_sec = mtim / 1000;
  4107   STAT_TIMESPEC (statb, st_mtim).tv_nsec = (mtim % 1000) * 1000000;
  4108 #else /* !STAT_TIMESPEC */
  4109   /* Headers supplied by the NDK r10b contain a `struct stat' without
  4110      POSIX fields for nano-second timestamps.  */
  4111   statb->st_mtime = mtim / 1000;
  4112   statb->st_mtime_nsec = (mtim % 1000) * 1000000;
  4113 #endif /* STAT_TIMESPEC */
  4114   statb->st_uid = getuid ();
  4115   statb->st_gid = getgid ();
  4116   return 0;
  4117 }
  4118 
  4119 /* Detect if Emacs has access to the document designated by the the
  4120    documen ID ID_NAME within the tree URI_NAME.  If ID_NAME is NULL,
  4121    use the document ID in URI_NAME itself.
  4122 
  4123    If WRITABLE, also check that the file is writable, which is true
  4124    if it is either a directory or its flags contains
  4125    FLAG_SUPPORTS_WRITE.
  4126 
  4127    Value is 0 if the file is accessible, and -1 with errno set
  4128    appropriately if not.  */
  4129 
  4130 static int
  4131 android_saf_access (const char *uri_name, const char *id_name,
  4132                     bool writable)
  4133 {
  4134   jmethodID method;
  4135   jstring uri, id;
  4136   jint rc;
  4137 
  4138   /* Now guarantee that it is safe to call functions which
  4139      synchronize with the SAF thread.  */
  4140 
  4141   if (inside_saf_critical_section)
  4142     {
  4143       errno = EIO;
  4144       return -1;
  4145     }
  4146 
  4147   /* Build strings for both URI and ID.  */
  4148   uri = (*android_java_env)->NewStringUTF (android_java_env, uri_name);
  4149   android_exception_check ();
  4150 
  4151   if (id_name)
  4152     {
  4153       id = (*android_java_env)->NewStringUTF (android_java_env,
  4154                                               id_name);
  4155       android_exception_check_1 (uri);
  4156     }
  4157   else
  4158     id = NULL;
  4159 
  4160   /* Try to retrieve the file status.  */
  4161   method = service_class.access_document;
  4162   inside_saf_critical_section = true;
  4163   rc = (*android_java_env)->CallNonvirtualIntMethod (android_java_env,
  4164                                                      emacs_service,
  4165                                                      service_class.class,
  4166                                                      method, uri, id,
  4167                                                      (jboolean) writable);
  4168   inside_saf_critical_section = false;
  4169 
  4170   /* Check for exceptions and release unneeded local references.  */
  4171 
  4172   if (id)
  4173     {
  4174       if (android_saf_exception_check (2, uri, id))
  4175         return -1;
  4176 
  4177       ANDROID_DELETE_LOCAL_REF (id);
  4178     }
  4179   else if (android_saf_exception_check (1, uri))
  4180     return -1;
  4181 
  4182   ANDROID_DELETE_LOCAL_REF (uri);
  4183 
  4184   switch (rc)
  4185     {
  4186     case -1:
  4187       /* -1 means it doesn't exist.  */
  4188       errno = ENOENT;
  4189       return -1;
  4190 
  4191     case -2:
  4192       /* -2 means access has been denied.  */
  4193       errno = EACCES;
  4194       return -1;
  4195 
  4196     case -3:
  4197       /* -3 refers to an internal error.  */
  4198       errno = EIO;
  4199       return -1;
  4200     }
  4201 
  4202   /* Return success.  */
  4203   return 0;
  4204 }
  4205 
  4206 /* Delete the document designated by DOC_ID within the tree identified
  4207    through the URI TREE.  Return 0 if the document has been deleted,
  4208    set errno and return -1 upon failure.
  4209 
  4210    DOC_NAME should be the name of the file itself, as a file name
  4211    whose constituent components lead to a document named DOC_ID.  It
  4212    isn't used to search for a document ID, but is used to invalidate
  4213    the file cache.  */
  4214 
  4215 static int
  4216 android_saf_delete_document (const char *tree, const char *doc_id,
  4217                              const char *doc_name)
  4218 {
  4219   jobject id, uri, name;
  4220   jmethodID method;
  4221   jint rc;
  4222 
  4223   /* Build the strings holding the ID, URI and NAME.  */
  4224   id = (*android_java_env)->NewStringUTF (android_java_env,
  4225                                           doc_id);
  4226   android_exception_check ();
  4227   uri = (*android_java_env)->NewStringUTF (android_java_env,
  4228                                            tree);
  4229   android_exception_check_1 (id);
  4230   name = (*android_java_env)->NewStringUTF (android_java_env,
  4231                                             doc_name);
  4232   android_exception_check_2 (id, name);
  4233 
  4234   /* Now, try to delete the document.  */
  4235   method = service_class.delete_document;
  4236   rc = (*android_java_env)->CallIntMethod (android_java_env,
  4237                                            emacs_service,
  4238                                            method, uri, id,
  4239                                            name);
  4240 
  4241   if (android_saf_exception_check (3, id, uri, name))
  4242     return -1;
  4243 
  4244   ANDROID_DELETE_LOCAL_REF (id);
  4245   ANDROID_DELETE_LOCAL_REF (uri);
  4246   ANDROID_DELETE_LOCAL_REF (name);
  4247 
  4248   if (rc)
  4249     {
  4250       errno = EACCES;
  4251       return -1;
  4252     }
  4253 
  4254   return 0;
  4255 }
  4256 
  4257 /* Declared further below.  */
  4258 static int android_document_id_from_name (const char *, const char *,
  4259                                           char **);
  4260 
  4261 /* Rename the document designated by DOC_ID inside the directory tree
  4262    identified by URI, which should be within the directory by the name
  4263    of DIR, to NAME.  If the document can't be renamed, return -1 and
  4264    set errno to a value describing the error.  Return 0 if the rename
  4265    is successful.
  4266 
  4267    Android permits the same document to appear in multiple
  4268    directories, but stores the display name inside the document
  4269    ``inode'' itself instead of the directory entries that refer to it.
  4270    Because of this, this operation may cause other directory entries
  4271    outside DIR to be renamed.  */
  4272 
  4273 static int
  4274 android_saf_rename_document (const char *uri, const char *doc_id,
  4275                              const char *dir, const char *name)
  4276 {
  4277   int rc;
  4278   jstring uri1, doc_id1, dir1, name1;
  4279   jmethodID method;
  4280 
  4281   /* Now build the strings for the URI, document ID, directory name
  4282      and directory ID.  */
  4283 
  4284   uri1 = (*android_java_env)->NewStringUTF (android_java_env, uri);
  4285   android_exception_check ();
  4286   doc_id1 = (*android_java_env)->NewStringUTF (android_java_env, doc_id);
  4287   android_exception_check_1 (uri1);
  4288   dir1 = (*android_java_env)->NewStringUTF (android_java_env, dir);
  4289   android_exception_check_2 (doc_id1, uri1);
  4290   name1 = (*android_java_env)->NewStringUTF (android_java_env, name);
  4291   android_exception_check_3 (dir1, doc_id1, uri1);
  4292 
  4293   method = service_class.rename_document;
  4294   rc = (*android_java_env)->CallNonvirtualIntMethod (android_java_env,
  4295                                                      emacs_service,
  4296                                                      service_class.class,
  4297                                                      method, uri1, doc_id1,
  4298                                                      dir1, name1);
  4299 
  4300   /* Check for exceptions.  */
  4301 
  4302   if (android_saf_exception_check (4, uri1, doc_id1, dir1, name1))
  4303     {
  4304       /* Substitute EXDEV for ENOSYS, so callers fall back on
  4305          delete-then-copy.  */
  4306 
  4307       if (errno == ENOSYS)
  4308         errno = EXDEV;
  4309 
  4310       return -1;
  4311     }
  4312 
  4313   /* Delete unused local references.  */
  4314   ANDROID_DELETE_LOCAL_REF (uri1);
  4315   ANDROID_DELETE_LOCAL_REF (doc_id1);
  4316   ANDROID_DELETE_LOCAL_REF (dir1);
  4317   ANDROID_DELETE_LOCAL_REF (name1);
  4318 
  4319   /* Then check for errors handled within the Java code.  */
  4320 
  4321   if (rc == -1)
  4322     {
  4323       /* UnsupportedOperationException.  Trick the caller into falling
  4324          back on delete-then-copy code.  */
  4325       errno = EXDEV;
  4326       return -1;
  4327     }
  4328 
  4329   return 0;
  4330 }
  4331 
  4332 /* Move the document designated by *DOC_ID from the directory under
  4333    DIR_NAME to the directory designated by DST_ID.  All three
  4334    directories are located within the tree identified by the given
  4335    URI.
  4336 
  4337    If the document's ID changes as a result of the movement, free
  4338    *DOC_ID and store the new document ID within.
  4339 
  4340    Value is 0 upon success, -1 otherwise with errno set.  */
  4341 
  4342 static int
  4343 android_saf_move_document (const char *uri, char **doc_id,
  4344                            const char *dir_name, const char *dst_id)
  4345 {
  4346   char *src_id, *id;
  4347   jobject uri1, doc_id1, dir_name1, dst_id1, src_id1;
  4348   jstring result;
  4349   jmethodID method;
  4350   int rc;
  4351   const char *new_id;
  4352 
  4353   /* Obtain the name of the source directory.  */
  4354   src_id = NULL;
  4355   rc = android_document_id_from_name (uri, dir_name, &src_id);
  4356 
  4357   if (rc != 1)
  4358     {
  4359       /* This file is either not a directory or nonexistent.  */
  4360       xfree (src_id);
  4361 
  4362       switch (rc)
  4363         {
  4364         case 0:
  4365           errno = ENOTDIR;
  4366           return -1;
  4367 
  4368         case -1:
  4369         case -2:
  4370           errno = ENOENT;
  4371           return -1;
  4372 
  4373         default:
  4374           emacs_abort ();
  4375         }
  4376     }
  4377 
  4378   /* Build Java strings for all five arguments.  */
  4379   id = *doc_id;
  4380   uri1 = (*android_java_env)->NewStringUTF (android_java_env, uri);
  4381   android_exception_check ();
  4382   doc_id1 = (*android_java_env)->NewStringUTF (android_java_env, id);
  4383   android_exception_check_1 (uri1);
  4384   dir_name1 = (*android_java_env)->NewStringUTF (android_java_env, dir_name);
  4385   android_exception_check_2 (doc_id1, uri1);
  4386   dst_id1 = (*android_java_env)->NewStringUTF (android_java_env, dst_id);
  4387   android_exception_check_3 (dir_name1, doc_id1, uri1);
  4388   src_id1 = (*android_java_env)->NewStringUTF (android_java_env, src_id);
  4389   xfree (src_id);
  4390   android_exception_check_4 (dst_id1, dir_name1, doc_id1, uri1);
  4391 
  4392   /* Do the rename.  */
  4393   method = service_class.move_document;
  4394   result = (*android_java_env)->CallObjectMethod (android_java_env,
  4395                                                   emacs_service,
  4396                                                   method, uri1,
  4397                                                   doc_id1, dir_name1,
  4398                                                   dst_id1, src_id1);
  4399   if (android_saf_exception_check (5, src_id1, dst_id1, dir_name1,
  4400                                    doc_id1, uri1))
  4401     {
  4402       /* Substitute EXDEV for ENOSYS, so callers fall back on
  4403          delete-then-copy.  */
  4404 
  4405       if (errno == ENOSYS)
  4406         errno = EXDEV;
  4407 
  4408       return -1;
  4409     }
  4410 
  4411   /* Delete unused local references.  */
  4412   ANDROID_DELETE_LOCAL_REF (src_id1);
  4413   ANDROID_DELETE_LOCAL_REF (dst_id1);
  4414   ANDROID_DELETE_LOCAL_REF (dir_name1);
  4415   ANDROID_DELETE_LOCAL_REF (doc_id1);
  4416   ANDROID_DELETE_LOCAL_REF (uri1);
  4417 
  4418   if (result)
  4419     {
  4420       /* The document ID changed.  Free id and replace *DOC_ID with
  4421          the new ID.  */
  4422       xfree (id);
  4423       new_id = (*android_java_env)->GetStringUTFChars (android_java_env,
  4424                                                        result, NULL);
  4425       android_exception_check_nonnull ((void *) new_id, result);
  4426       *doc_id = xstrdup (new_id);
  4427       (*android_java_env)->ReleaseStringUTFChars (android_java_env, result,
  4428                                                   new_id);
  4429       ANDROID_DELETE_LOCAL_REF (result);
  4430     }
  4431 
  4432   return 0;
  4433 }
  4434 
  4435 
  4436 
  4437 /* SAF directory vnode.  A file within a SAF directory tree is
  4438    identified by the URI of the directory tree itself, an opaque
  4439    ``file identifier'' value, and a display name.  This information is
  4440    recorded in each vnode representing either a directory or a file
  4441    itself.  */
  4442 
  4443 struct android_saf_tree_vnode
  4444 {
  4445   /* The vnode data itself.  */
  4446   struct android_vnode vnode;
  4447 
  4448   /* The URI of the directory tree represented.  This is Java string
  4449      data in ``modified UTF format'', which is essentially a modified
  4450      UTF-8 format capable of storing NULL bytes while also utilizing
  4451      NULL termination.  */
  4452   const char *tree_uri;
  4453 
  4454   /* The ID of the document tree designated by TREE_URI.  */
  4455   char *tree_id;
  4456 
  4457   /* The document ID of the directory represented, or NULL if this is
  4458      the root directory of the tree.  Since file and new vnodes don't
  4459      represent the root directory, this field is always set in
  4460      them.  */
  4461   char *document_id;
  4462 
  4463   /* The file name of this tree vnode.  This is a ``path'' to the
  4464      file, where each directory component consists of the display name
  4465      of a directory leading up to a file within, terminated with a
  4466      directory separator character.  */
  4467   char *name;
  4468 };
  4469 
  4470 struct android_saf_tree_vdir
  4471 {
  4472   /* The virtual directory stream function table.  */
  4473   struct android_vdir vdir;
  4474 
  4475   /* The next directory in `all_saf_tree_vdirs'.  */
  4476   struct android_saf_tree_vdir *next;
  4477 
  4478   /* Name of this directory relative to the root file system.  */
  4479   char *name;
  4480 
  4481   /* Local reference to the cursor representing the directory
  4482      stream.  */
  4483   jobject cursor;
  4484 
  4485   /* The ``directory'' file descriptor used to identify this directory
  4486      stream, or -1.  */
  4487   int fd;
  4488 };
  4489 
  4490 static struct android_vnode *android_saf_tree_name (struct android_vnode *,
  4491                                                     char *, size_t);
  4492 static int android_saf_tree_open (struct android_vnode *, int,
  4493                                   mode_t, bool, int *, AAsset **);
  4494 static void android_saf_tree_close (struct android_vnode *);
  4495 static int android_saf_tree_unlink (struct android_vnode *);
  4496 static int android_saf_tree_symlink (const char *, struct android_vnode *);
  4497 static int android_saf_tree_rmdir (struct android_vnode *);
  4498 static int android_saf_tree_rename (struct android_vnode *,
  4499                                     struct android_vnode *, bool);
  4500 static int android_saf_tree_stat (struct android_vnode *, struct stat *);
  4501 static int android_saf_tree_access (struct android_vnode *, int);
  4502 static int android_saf_tree_mkdir (struct android_vnode *, mode_t);
  4503 static int android_saf_tree_chmod (struct android_vnode *, mode_t, int);
  4504 static ssize_t android_saf_tree_readlink (struct android_vnode *, char *,
  4505                                           size_t);
  4506 static struct android_vdir *android_saf_tree_opendir (struct android_vnode *);
  4507 
  4508 /* Vector of VFS operations associated with SAF tree VFS nodes.  */
  4509 
  4510 static struct android_vops saf_tree_vfs_ops =
  4511   {
  4512     android_saf_tree_name,
  4513     android_saf_tree_open,
  4514     android_saf_tree_close,
  4515     android_saf_tree_unlink,
  4516     android_saf_tree_symlink,
  4517     android_saf_tree_rmdir,
  4518     android_saf_tree_rename,
  4519     android_saf_tree_stat,
  4520     android_saf_tree_access,
  4521     android_saf_tree_mkdir,
  4522     android_saf_tree_chmod,
  4523     android_saf_tree_readlink,
  4524     android_saf_tree_opendir,
  4525   };
  4526 
  4527 /* Vector of VFS operations associated with SAF file VFS nodes.
  4528    Defined later in the next page.  */
  4529 static struct android_vops saf_file_vfs_ops;
  4530 
  4531 /* Vector of VFS operations associated with SAF ``new'' VFS nodes.
  4532    Defined two pages below.  */
  4533 static struct android_vops saf_new_vfs_ops;
  4534 
  4535 /* Chain of all open SAF directory streams.  */
  4536 static struct android_saf_tree_vdir *all_saf_tree_vdirs;
  4537 
  4538 /* Find the document ID of the file within TREE_URI designated by
  4539    NAME.
  4540 
  4541    NAME is a ``file name'' comprised of the display names of
  4542    individual files.  Each constituent component prior to the last
  4543    must name a directory file within TREE_URI.
  4544 
  4545    If NAME is not correct for the Java ``modified UTF-8'' coding
  4546    system, return -1 and set errno to ENOENT.
  4547 
  4548    Upon success, return 0 or 1 (contingent upon whether or not the
  4549    last component within NAME is a directory) and place the document
  4550    ID of the named file in ID.
  4551 
  4552    If the designated file doesn't exist, but the penultimate component
  4553    within NAME does and is also a directory, return -2 and place the
  4554    document ID of that directory within *ID.
  4555 
  4556    If the designated file can't be located, return -1 and set errno
  4557    accordingly.  The reasons for which a file can't be located are not
  4558    all immediately obvious: quitting, for example, can cause document
  4559    ID lookup to be canceled.  */
  4560 
  4561 static int
  4562 android_document_id_from_name (const char *tree_uri, const char *name,
  4563                                char **id)
  4564 {
  4565   jobjectArray result;
  4566   jstring uri;
  4567   jbyteArray java_name;
  4568   jint rc;
  4569   jmethodID method;
  4570   const char *doc_id;
  4571 
  4572   /* Verify the format of NAME.  Don't allow creating files that
  4573      contain characters that can't be encoded in Java.  */
  4574 
  4575   if (android_verify_jni_string (name))
  4576     {
  4577       errno = ENOENT;
  4578       return -1;
  4579     }
  4580 
  4581   /* Now guarantee that it is safe to call
  4582      `document_id_from_name'.  */
  4583 
  4584   if (inside_saf_critical_section)
  4585     {
  4586       errno = EIO;
  4587       return -1;
  4588     }
  4589 
  4590   /* First, create the array that will hold the result.  */
  4591   result = (*android_java_env)->NewObjectArray (android_java_env, 1,
  4592                                                 java_string_class,
  4593                                                 NULL);
  4594   android_exception_check ();
  4595 
  4596   /* Next, create the string for the tree URI and name.  */
  4597   java_name = (*android_java_env)->NewStringUTF (android_java_env,
  4598                                                  name);
  4599   android_exception_check_1 (result);
  4600   uri = (*android_java_env)->NewStringUTF (android_java_env, tree_uri);
  4601   android_exception_check_2 (result, java_name);
  4602 
  4603   /* Now, call documentIdFromName.  This will synchronize with the SAF
  4604      thread, so make sure reentrant calls don't happen.  */
  4605   method = service_class.document_id_from_name;
  4606   inside_saf_critical_section = true;
  4607   rc = (*android_java_env)->CallNonvirtualIntMethod (android_java_env,
  4608                                                      emacs_service,
  4609                                                      service_class.class,
  4610                                                      method,
  4611                                                      uri, java_name,
  4612                                                      result);
  4613   inside_saf_critical_section = false;
  4614 
  4615   if (android_saf_exception_check (3, result, uri, java_name))
  4616     return -1;
  4617 
  4618   ANDROID_DELETE_LOCAL_REF (uri);
  4619   ANDROID_DELETE_LOCAL_REF (java_name);
  4620 
  4621   /* If rc indicates failure, don't try to copy from result.  */
  4622 
  4623   if (rc == -1)
  4624     {
  4625       ANDROID_DELETE_LOCAL_REF (result);
  4626       errno = ENOENT;
  4627       return -1;
  4628     }
  4629 
  4630   eassert (rc == -2 || rc >= 0);
  4631 
  4632   /* Otherwise, obtain the contents of the string returned in Java
  4633      ``UTF-8'' encoding.  */
  4634   uri = (*android_java_env)->GetObjectArrayElement (android_java_env,
  4635                                                     result, 0);
  4636   android_exception_check_nonnull (uri, result);
  4637   ANDROID_DELETE_LOCAL_REF (result);
  4638 
  4639   doc_id = (*android_java_env)->GetStringUTFChars (android_java_env,
  4640                                                    uri, NULL);
  4641   android_exception_check_nonnull ((void *) doc_id, uri);
  4642 
  4643   /* Make *ID its copy.  */
  4644   *id = xstrdup (doc_id);
  4645 
  4646   /* And release it.  */
  4647   (*android_java_env)->ReleaseStringUTFChars (android_java_env,
  4648                                               (jstring) uri, doc_id);
  4649   ANDROID_DELETE_LOCAL_REF (uri);
  4650   return rc;
  4651 }
  4652 
  4653 static struct android_vnode *
  4654 android_saf_tree_name (struct android_vnode *vnode, char *name,
  4655                        size_t length)
  4656 {
  4657   char *remainder;
  4658   int rc;
  4659   struct android_saf_tree_vnode *vp, *new;
  4660   size_t vp_length;
  4661   char *filename, *fill, *doc_id, *end;
  4662   struct android_saf_root_vnode root;
  4663   struct android_saf_tree_vnode tree;
  4664 
  4665   /* Canonicalize NAME.  */
  4666   remainder = android_vfs_canonicalize_name (name, &length);
  4667 
  4668   /* If remainder is set, it's a name relative to the root vnode.  */
  4669   if (remainder)
  4670     goto parent_vnode;
  4671 
  4672   /* If LENGTH is empty or NAME is a single directory separator,
  4673      return a copy of this vnode.  */
  4674 
  4675   if (length < 1 || (*name == '/' && length == 1))
  4676     {
  4677       vp = xmalloc (sizeof *vp);
  4678       memcpy (vp, vnode, sizeof *vp);
  4679 
  4680       /* Duplicate the information contained within VNODE.  */
  4681 
  4682       vp->tree_uri = xstrdup (vp->tree_uri);
  4683       vp->tree_id = xstrdup (vp->tree_id);
  4684       vp->name = xstrdup (vp->name);
  4685 
  4686       if (vp->document_id)
  4687         vp->document_id = xstrdup (vp->name);
  4688 
  4689       return &vp->vnode;
  4690     }
  4691 
  4692   /* Now, search for the document ID of the file designated by NAME
  4693      relative to this vnode.  */
  4694 
  4695   vp = (struct android_saf_tree_vnode *) vnode;
  4696   vp_length = strlen (vp->name);
  4697 
  4698   /* If NAME starts with a directory separator, move it past that.  */
  4699 
  4700   if (*name == '/')
  4701     name++, length -= 1;
  4702 
  4703   /* Concatenate VP->name with NAME.  Leave one byte at the end for an
  4704      extra trailing directory separator.  */
  4705 
  4706   filename = xmalloc (vp_length + length + 2);
  4707   fill = stpcpy (filename, vp->name);
  4708   fill = stpcpy (fill, name);
  4709 
  4710   /* And search for a document ID in the result.  */
  4711   rc = android_document_id_from_name (vp->tree_uri, name,
  4712                                       &doc_id);
  4713 
  4714   if (rc < 0)
  4715     {
  4716       if (rc == -2)
  4717         {
  4718           /* This is a vnode representing a nonexistent file in a real
  4719              directory, so create a vnode whose sole use is to create
  4720              the file.  */
  4721 
  4722           new = xmalloc (sizeof *new);
  4723           new->vnode.ops = &saf_new_vfs_ops;
  4724           new->vnode.type = ANDROID_VNODE_SAF_NEW;
  4725           new->vnode.flags = 0;
  4726 
  4727           /* Here, doc_id is actually the ID of the penultimate
  4728              component in NAME.  */
  4729 
  4730           new->document_id = doc_id;
  4731           new->tree_uri = xstrdup (vp->tree_uri);
  4732           new->tree_id = xstrdup (vp->tree_id);
  4733           new->name = filename;
  4734           return &new->vnode;
  4735         }
  4736 
  4737       /* The document ID can't be found.  */
  4738       xfree (filename);
  4739       return NULL;
  4740     }
  4741 
  4742   if (!rc)
  4743     {
  4744       /* rc set to 0 means that NAME is a regular file.  Detect if
  4745          NAME is supposed to be a directory; if it is, set errno to
  4746          ENODIR.  */
  4747 
  4748       if (name[length - 1] == '/')
  4749         {
  4750           xfree (filename);
  4751           xfree (doc_id);
  4752           errno = ENOTDIR;
  4753           return NULL;
  4754         }
  4755     }
  4756 
  4757   /* So this is either a directory or really a file.  Fortunately,
  4758      directory and file vnodes share everything in common except for a
  4759      few file operations, so create a new directory vnode with the new
  4760      file name and return it.  */
  4761 
  4762   new = xmalloc (sizeof *new);
  4763   new->vnode.ops = (rc ? &saf_tree_vfs_ops
  4764                     : &saf_file_vfs_ops);
  4765   new->vnode.type = (rc ? ANDROID_VNODE_SAF_TREE
  4766                      : ANDROID_VNODE_SAF_FILE);
  4767   new->vnode.flags = 0;
  4768 
  4769   if (rc)
  4770     {
  4771       /* If fill[-1] is not a directory separator character, append
  4772          one to the end of filename.  */
  4773 
  4774       if (fill[-1] != '/')
  4775         {
  4776           *fill++ = '/';
  4777           *fill   = '\0';
  4778         }
  4779     }
  4780 
  4781   new->document_id = doc_id;
  4782   new->tree_uri = xstrdup (vp->tree_uri);
  4783   new->tree_id = xstrdup (vp->tree_id);
  4784   new->name = filename;
  4785   return &new->vnode;
  4786 
  4787  parent_vnode:
  4788   vp = (struct android_saf_tree_vnode *) vnode;
  4789 
  4790   /* .. was encountered and the parent couldn't be found through
  4791      stripping off preceding components.
  4792 
  4793      Find the parent vnode and name the rest of NAME starting from
  4794      there.  */
  4795 
  4796   if (!vp->document_id)
  4797     {
  4798       /* VP->document_id is NULL, meaning this is the root of this
  4799          directory tree.  The parent vnode is an SAF root vnode with
  4800          VP->tree_uri's authority.  */
  4801 
  4802       root.vnode.ops = &saf_root_vfs_ops;
  4803       root.vnode.type = ANDROID_VNODE_SAF_ROOT;
  4804       root.vnode.flags = 0;
  4805 
  4806       /* Find the authority from the URI.  */
  4807 
  4808       fill = (char *) vp->tree_uri;
  4809 
  4810       if (strncmp (fill, "content://", 10))
  4811         emacs_abort ();
  4812 
  4813       /* Skip the content header.  */
  4814       fill += sizeof "content://" - 1;
  4815 
  4816       /* The authority segment of the URI is between here and the
  4817          next slash.  */
  4818 
  4819       end = strchr (fill, '/');
  4820 
  4821       if (!end)
  4822         emacs_abort ();
  4823 
  4824       root.authority = xmalloc (end - fill + 1);
  4825       memcpy (root.authority, fill, end - fill);
  4826       root.authority[end - fill] = '\0';
  4827 
  4828       /* Now search using this vnode.  */
  4829       vnode = (*root.vnode.ops->name) (&root.vnode, remainder,
  4830                                        strlen (remainder));
  4831       xfree (root.authority);
  4832       return vnode;
  4833     }
  4834 
  4835   /* Otherwise, strip off the last directory component.  */
  4836 
  4837   fill = strrchr (vp->name, '/');
  4838   if (!fill)
  4839     emacs_abort ();
  4840 
  4841   /* Create a new vnode at the top of the directory tree, and search
  4842      for remainder from there.  */
  4843 
  4844   tree.vnode.ops = &saf_tree_vfs_ops;
  4845   tree.vnode.type = ANDROID_VNODE_SAF_TREE;
  4846   tree.vnode.flags = 0;
  4847   tree.document_id = NULL;
  4848   tree.name = (char *) "/";
  4849   tree.tree_uri = vp->tree_uri;
  4850   tree.tree_id = vp->tree_id;
  4851 
  4852   length   = strlen (remainder + (*remainder == '/'));
  4853   filename = xmalloc (fill - vp->name + length + 2);
  4854   fill = mempcpy (filename, vp->name,
  4855                   /* Include the separator character (*FILL) within
  4856                      this copy.  */
  4857                   fill - vp->name + 1);
  4858   /* Skip a leading separator in REMAINDER.  */
  4859   strcpy (fill, remainder + (*remainder == '/'));
  4860 
  4861   /* Use this filename to find a vnode relative to the start of this
  4862      tree.  */
  4863 
  4864   vnode = android_saf_tree_name (&tree.vnode, filename,
  4865                                  strlen (filename));
  4866   xfree (filename);
  4867   return vnode;
  4868 }
  4869 
  4870 static int
  4871 android_saf_tree_open (struct android_vnode *vnode, int flags,
  4872                        mode_t mode, bool asset_p, int *fd,
  4873                        AAsset **asset)
  4874 {
  4875   /* Don't allow opening this special directory.  */
  4876   errno = ENOSYS;
  4877   return -1;
  4878 }
  4879 
  4880 static void
  4881 android_saf_tree_close (struct android_vnode *vnode)
  4882 {
  4883   struct android_saf_tree_vnode *vp;
  4884   int save_errno;
  4885 
  4886   vp = (struct android_saf_tree_vnode *) vnode;
  4887 
  4888   save_errno = errno;
  4889   xfree ((void *) vp->tree_uri);
  4890   xfree (vp->tree_id);
  4891   xfree (vp->name);
  4892   xfree (vp->document_id);
  4893   xfree (vp);
  4894   errno = save_errno;
  4895 }
  4896 
  4897 static int
  4898 android_saf_tree_unlink (struct android_vnode *vnode)
  4899 {
  4900   errno = EISDIR;
  4901   return -1;
  4902 }
  4903 
  4904 static int
  4905 android_saf_tree_symlink (const char *target, struct android_vnode *vnode)
  4906 {
  4907   errno = EPERM;
  4908   return -1;
  4909 }
  4910 
  4911 static int
  4912 android_saf_tree_rmdir (struct android_vnode *vnode)
  4913 {
  4914   struct android_saf_tree_vnode *vp;
  4915 
  4916   vp = (struct android_saf_tree_vnode *) vnode;
  4917 
  4918   /* Don't allow deleting the root directory.  */
  4919 
  4920   if (!vp->document_id)
  4921     {
  4922       errno = EROFS;
  4923       return -1;
  4924     }
  4925 
  4926   return android_saf_delete_document (vp->tree_uri,
  4927                                       vp->document_id,
  4928                                       vp->name);
  4929 }
  4930 
  4931 static int
  4932 android_saf_tree_rename (struct android_vnode *src,
  4933                          struct android_vnode *dst,
  4934                          bool keep_existing)
  4935 {
  4936   char *last, *dst_last;
  4937   struct android_saf_tree_vnode *vp, *vdst;
  4938   char path[PATH_MAX], path1[PATH_MAX];
  4939   char *fill, *dst_id;
  4940   int rc;
  4941 
  4942   /* If dst isn't a tree, file or new vnode, return EXDEV.  */
  4943 
  4944   if (dst->type != ANDROID_VNODE_SAF_TREE
  4945       && dst->type != ANDROID_VNODE_SAF_FILE
  4946       && dst->type != ANDROID_VNODE_SAF_NEW)
  4947     {
  4948       errno = EXDEV;
  4949       return -1;
  4950     }
  4951 
  4952   vp = (struct android_saf_tree_vnode *) src;
  4953   vdst = (struct android_saf_tree_vnode *) dst;
  4954 
  4955   /* if vp and vdst refer to different tree URIs, return EXDEV.  */
  4956 
  4957   if (strcmp (vp->tree_uri, vdst->tree_uri))
  4958     {
  4959       errno = EXDEV;
  4960       return -1;
  4961     }
  4962 
  4963   /* If `keep_existing' and the destination vnode designates an
  4964      existing file, return EEXIST.  */
  4965 
  4966   if (keep_existing && dst->type != ANDROID_VNODE_SAF_NEW)
  4967     {
  4968       errno = EEXIST;
  4969       return -1;
  4970     }
  4971 
  4972   /* Unix `rename' maps to two Android content provider operations.
  4973      The first case is a simple rename, where src and dst are both
  4974      located within the same directory.  Compare the file names of
  4975      both up to the component before the last.  */
  4976 
  4977   last = strrchr (vp->name, '/');
  4978   eassert (last != NULL);
  4979 
  4980   if (last[1] == '\0')
  4981     {
  4982       if (last == vp->name)
  4983         {
  4984           /* This means the caller is trying to rename the root
  4985              directory of the tree.  */
  4986           errno = EROFS;
  4987           return -1;
  4988         }
  4989 
  4990       /* The name is terminated by a trailing directory separator.
  4991          Search backwards for the preceding directory separator.  */
  4992       last = memrchr (vp->name, '/', last - vp->name);
  4993       eassert (last != NULL);
  4994     }
  4995 
  4996   /* Find the end of the second-to-last component in vdst's name.  */
  4997 
  4998   dst_last = strrchr (vdst->name, '/');
  4999   eassert (dst_last != NULL);
  5000 
  5001   if (dst_last[1] == '\0')
  5002     {
  5003       if (dst_last == vdst->name)
  5004         {
  5005           /* Forbid overwriting the root of the tree either.  */
  5006           errno = EROFS;
  5007           return -1;
  5008         }
  5009 
  5010       dst_last = memrchr (vdst->name, '/', dst_last - vdst->name);
  5011       eassert (dst_last != NULL);
  5012     }
  5013 
  5014   if (dst_last - vdst->name != last - vp->name
  5015       || memcmp (vp->name, vdst->name, last - vp->name))
  5016     {
  5017       /* The second case is where the file must be moved from one
  5018          directory to the other, and possibly then recreated under a
  5019          new name.  */
  5020 
  5021       /* The names of the source and destination directories will have
  5022          to be copied to path.  */
  5023 
  5024       if (last - vp->name >= PATH_MAX
  5025           || dst_last - vdst->name >= PATH_MAX)
  5026         {
  5027           errno = ENAMETOOLONG;
  5028           return -1;
  5029         }
  5030 
  5031       fill = mempcpy (path, vp->name, last - vp->name);
  5032       *fill = '\0';
  5033 
  5034       /* If vdst doesn't already exist, its document_id field is
  5035          already the name of its parent directory.  */
  5036 
  5037       if (dst->type == ANDROID_VNODE_SAF_NEW)
  5038         {
  5039           /* First, move the document.  This will update
  5040              VP->document_id if it changes.  */
  5041 
  5042           if (android_saf_move_document (vp->tree_uri,
  5043                                          &vp->document_id,
  5044                                          path,
  5045                                          vdst->document_id))
  5046             return -1;
  5047 
  5048           fill = mempcpy (path, vdst->name, dst_last - vdst->name);
  5049           *fill = '\0';
  5050 
  5051           /* Next, rename the document, if its display name differs
  5052              from that of the source.  */
  5053 
  5054           if (strcmp (dst_last + 1, last + 1)
  5055               /* By now vp->document_id is already in the destination
  5056                  directory.  */
  5057               && android_saf_rename_document (vp->tree_uri,
  5058                                               vp->document_id,
  5059                                               path,
  5060                                               dst_last + 1))
  5061             return -1;
  5062 
  5063           return 0;
  5064         }
  5065 
  5066       /* Retrieve the ID designating the destination document's parent
  5067          directory.  */
  5068 
  5069       fill = mempcpy (path1, vdst->name, dst_last - vdst->name);
  5070       *fill = '\0';
  5071 
  5072       rc = android_document_id_from_name (vp->tree_uri,
  5073                                           path1, &dst_id);
  5074 
  5075       if (rc != 1)
  5076         {
  5077           /* This file is either not a directory or nonexistent.  */
  5078 
  5079           switch (rc)
  5080             {
  5081             case 0:
  5082               errno = ENOTDIR;
  5083               goto error;
  5084 
  5085             case -1:
  5086               /* dst_id is not set here, as the penultimate component
  5087                  also couldn't be located.  */
  5088               errno = ENOENT;
  5089               return -1;
  5090 
  5091             case -2:
  5092               errno = ENOENT;
  5093               goto error;
  5094 
  5095             default:
  5096               emacs_abort ();
  5097             }
  5098         }
  5099 
  5100       /* vdst already exists, so it needs to be deleted first.  */
  5101 
  5102       if (android_saf_delete_document (vdst->tree_uri,
  5103                                        vdst->document_id,
  5104                                        vdst->name))
  5105         goto error;
  5106 
  5107       /* First, move the document.  This will update
  5108          VP->document_id if it changes.  */
  5109 
  5110       if (android_saf_move_document (vp->tree_uri,
  5111                                      &vp->document_id,
  5112                                      path, dst_id))
  5113         goto error;
  5114 
  5115       /* Next, rename the document, if its display name differs from
  5116          that of the source.  */
  5117 
  5118       if (strcmp (dst_last + 1, last + 1)
  5119           /* By now vp->document_id is already in the destination
  5120              directory.  */
  5121           && android_saf_rename_document (vp->tree_uri,
  5122                                           vp->document_id,
  5123                                           path1,
  5124                                           dst_last + 1))
  5125         goto error;
  5126 
  5127       xfree (dst_id);
  5128       return 0;
  5129 
  5130     error:
  5131       xfree (dst_id);
  5132       return 1;
  5133     }
  5134 
  5135   /* Otherwise, do this simple rename.  The name of the parent
  5136      directory is required, as it provides the directory whose entries
  5137      will be modified.  */
  5138 
  5139   if (last - vp->name >= PATH_MAX)
  5140     {
  5141       errno = ENAMETOOLONG;
  5142       return -1;
  5143     }
  5144 
  5145   /* If the destination document exists, delete it.  */
  5146 
  5147   if (dst->type != ANDROID_VNODE_SAF_NEW
  5148       && android_saf_delete_document (vdst->tree_uri,
  5149                                       vdst->document_id,
  5150                                       vdst->name))
  5151     return -1;
  5152 
  5153   fill = mempcpy (path, vp->name, last - vp->name);
  5154   *fill = '\0';
  5155   return android_saf_rename_document (vp->tree_uri,
  5156                                       vp->document_id,
  5157                                       path,
  5158                                       dst_last + 1);
  5159 }
  5160 
  5161 static int
  5162 android_saf_tree_stat (struct android_vnode *vnode,
  5163                        struct stat *statb)
  5164 {
  5165   struct android_saf_tree_vnode *vp;
  5166 
  5167   vp = (struct android_saf_tree_vnode *) vnode;
  5168 
  5169   return android_saf_stat (vp->tree_uri, vp->document_id,
  5170                            statb, false);
  5171 }
  5172 
  5173 static int
  5174 android_saf_tree_access (struct android_vnode *vnode, int mode)
  5175 {
  5176   struct android_saf_tree_vnode *vp;
  5177 
  5178   vp = (struct android_saf_tree_vnode *) vnode;
  5179 
  5180   /* Validate MODE.  */
  5181 
  5182   if (mode != F_OK && !(mode & (W_OK | X_OK | R_OK)))
  5183     {
  5184       errno = EINVAL;
  5185       return -1;
  5186     }
  5187 
  5188   return android_saf_access (vp->tree_uri, vp->document_id,
  5189                              mode & W_OK);
  5190 }
  5191 
  5192 static int
  5193 android_saf_tree_mkdir (struct android_vnode *vnode, mode_t mode)
  5194 {
  5195   /* Since tree vnodes represent files that already exist, return
  5196      EEXIST.  */
  5197   errno = EEXIST;
  5198   return -1;
  5199 }
  5200 
  5201 static int
  5202 android_saf_tree_chmod (struct android_vnode *vnode, mode_t mode,
  5203                         int flags)
  5204 {
  5205   /* Return EACCESS should MODE contain unusual bits besides the
  5206      standard file access permissions.  */
  5207 
  5208   if (mode & ~0777)
  5209     {
  5210       errno = EACCES;
  5211       return -1;
  5212     }
  5213 
  5214   /* Otherwise, no further action is necessary, as SAF nodes already
  5215      pretend to be S_IRUSR | S_IWUSR.  */
  5216   return 0;
  5217 }
  5218 
  5219 static ssize_t
  5220 android_saf_tree_readlink (struct android_vnode *vnode, char *buffer,
  5221                            size_t size)
  5222 {
  5223   /* Return EINVAL.  Symlinks aren't exposed to clients by the
  5224      SAF.  */
  5225   errno = EINVAL;
  5226   return -1;
  5227 }
  5228 
  5229 /* Open a database Cursor containing each directory entry within the
  5230    supplied SAF tree vnode VP.
  5231 
  5232    Value is NULL upon failure with errno set to a suitable value, a
  5233    local reference to the Cursor object otherwise.  */
  5234 
  5235 static jobject
  5236 android_saf_tree_opendir_1 (struct android_saf_tree_vnode *vp)
  5237 {
  5238   jobject uri, id, cursor;
  5239   jmethodID method;
  5240 
  5241   if (inside_saf_critical_section)
  5242     {
  5243       errno = EIO;
  5244       return NULL;
  5245     }
  5246 
  5247   /* Build strings for both URI and ID.  */
  5248   uri = (*android_java_env)->NewStringUTF (android_java_env,
  5249                                            vp->tree_uri);
  5250   android_exception_check ();
  5251 
  5252   if (vp->document_id)
  5253     {
  5254       id = (*android_java_env)->NewStringUTF (android_java_env,
  5255                                               vp->document_id);
  5256       android_exception_check_1 (uri);
  5257     }
  5258   else
  5259     id = NULL;
  5260 
  5261   /* Try to open the cursor.  */
  5262   method = service_class.open_document_directory;
  5263   inside_saf_critical_section = true;
  5264   cursor
  5265     = (*android_java_env)->CallNonvirtualObjectMethod (android_java_env,
  5266                                                        emacs_service,
  5267                                                        service_class.class,
  5268                                                        method, uri, id);
  5269   inside_saf_critical_section = false;
  5270 
  5271   if (id)
  5272     {
  5273       if (android_saf_exception_check (2, id, uri))
  5274         return NULL;
  5275 
  5276       ANDROID_DELETE_LOCAL_REF (id);
  5277     }
  5278   else if (android_saf_exception_check (1, uri))
  5279     return NULL;
  5280 
  5281   ANDROID_DELETE_LOCAL_REF (uri);
  5282 
  5283   /* Return the resulting cursor.  */
  5284   return cursor;
  5285 }
  5286 
  5287 static struct dirent *
  5288 android_saf_tree_readdir (struct android_vdir *vdir)
  5289 {
  5290   struct android_saf_tree_vdir *dir;
  5291   static struct dirent *dirent;
  5292   jobject entry, d_name;
  5293   jint d_type;
  5294   jmethodID method;
  5295   size_t length, size;
  5296   const char *chars;
  5297 
  5298   dir = (struct android_saf_tree_vdir *) vdir;
  5299 
  5300   /* Try to read one entry from the cursor.  */
  5301   method = service_class.read_directory_entry;
  5302   entry
  5303     = (*android_java_env)->CallNonvirtualObjectMethod (android_java_env,
  5304                                                        emacs_service,
  5305                                                        service_class.class,
  5306                                                        method, dir->cursor);
  5307   android_exception_check ();
  5308 
  5309   /* If ENTRY is NULL, we're at the end of the directory.  */
  5310 
  5311   if (!entry)
  5312     {
  5313       xfree (entry);
  5314       entry = NULL;
  5315       return NULL;
  5316     }
  5317 
  5318   /* Load both fields from ENTRY.  */
  5319   d_name = (*android_java_env)->GetObjectField (android_java_env, entry,
  5320                                                 entry_class.d_name);
  5321   if (!d_name)
  5322     {
  5323       /* If an error transpires, d_name is set to NULL.  */
  5324       (*android_java_env)->ExceptionClear (android_java_env);
  5325       ANDROID_DELETE_LOCAL_REF (entry);
  5326 
  5327       /* XXX: what would be a better error indication? */
  5328       errno = EIO;
  5329       return NULL;
  5330     }
  5331 
  5332   /* d_type is 1 if this is a directory, and 0 if it's a regular
  5333      file.  */
  5334   d_type = (*android_java_env)->GetIntField (android_java_env, entry,
  5335                                              entry_class.d_type);
  5336   ANDROID_DELETE_LOCAL_REF (entry);
  5337 
  5338   /* Copy the name of the directory over.  */
  5339   chars = (*android_java_env)->GetStringUTFChars (android_java_env,
  5340                                                   (jstring) d_name,
  5341                                                   NULL);
  5342   android_exception_check_nonnull ((void *) chars, d_name);
  5343 
  5344   /* Figure out how large it is, and then resize dirent to fit.  */
  5345   length = strlen (chars) + 1;
  5346   size   = offsetof (struct dirent, d_name) + length;
  5347   dirent = xrealloc (dirent, size);
  5348 
  5349   /* Clear dirent.  */
  5350   memset (dirent, 0, size);
  5351 
  5352   /* Fill in the generic directory information and copy the string
  5353      over.  */
  5354   dirent->d_ino = 0;
  5355   dirent->d_off = 0;
  5356   dirent->d_reclen = size;
  5357   dirent->d_type = d_type ? DT_DIR : DT_UNKNOWN;
  5358   strcpy (dirent->d_name, chars);
  5359 
  5360   /* Release the string data and the local reference to STRING.  */
  5361   (*android_java_env)->ReleaseStringUTFChars (android_java_env,
  5362                                               (jstring) d_name,
  5363                                               chars);
  5364   ANDROID_DELETE_LOCAL_REF (d_name);
  5365   return dirent;
  5366 }
  5367 
  5368 static void
  5369 android_saf_tree_closedir (struct android_vdir *vdir)
  5370 {
  5371   struct android_saf_tree_vdir *dir, **next, *tem;
  5372 
  5373   dir = (struct android_saf_tree_vdir *) vdir;
  5374 
  5375   /* dir->name is allocated by asprintf, which uses regular
  5376      malloc.  */
  5377   free (dir->name);
  5378 
  5379   /* Yes, DIR->cursor is a local reference.  */
  5380   ANDROID_DELETE_LOCAL_REF (dir->cursor);
  5381 
  5382   /* If the ``directory file descriptor'' has been opened, close
  5383      it.  */
  5384   if (dir->fd != -1)
  5385     close (dir->fd);
  5386 
  5387   /* Now unlink this directory.  */
  5388 
  5389   for (next = &all_saf_tree_vdirs; (tem = *next);)
  5390     {
  5391       if (tem == dir)
  5392         *next = dir->next;
  5393       else
  5394         next = &(*next)->next;
  5395     }
  5396 
  5397   xfree (dir);
  5398 }
  5399 
  5400 static int
  5401 android_saf_tree_dirfd (struct android_vdir *vdir)
  5402 {
  5403   struct android_saf_tree_vdir *dir;
  5404 
  5405   dir = (struct android_saf_tree_vdir *) vdir;
  5406 
  5407   /* Since `android_saf_tree_opendir' tries to avoid opening a file
  5408      descriptor if readdir isn't called, dirfd can fail if open fails.
  5409 
  5410      open sets errno to a set of errors different from what POSIX
  5411      stipulates for dirfd, but for ease of implementation the open
  5412      errors are used instead.  */
  5413 
  5414   if (dir->fd >= 0)
  5415     return dir->fd;
  5416 
  5417   dir->fd = open ("/dev/null", O_RDONLY | O_CLOEXEC);
  5418   return dir->fd;
  5419 }
  5420 
  5421 static struct android_vdir *
  5422 android_saf_tree_opendir (struct android_vnode *vnode)
  5423 {
  5424   struct android_saf_tree_vnode *vp;
  5425   struct android_saf_tree_vdir *dir;
  5426   char *fill, *end;
  5427   jobject cursor;
  5428   char component[PATH_MAX];
  5429 
  5430   vp = (struct android_saf_tree_vnode *) vnode;
  5431 
  5432   /* First, fill the directory stream with the right functions and
  5433      file name.  */
  5434 
  5435   dir = xmalloc (sizeof *dir);
  5436   dir->vdir.readdir = android_saf_tree_readdir;
  5437   dir->vdir.closedir = android_saf_tree_closedir;
  5438   dir->vdir.dirfd = android_saf_tree_dirfd;
  5439 
  5440   /* Find the authority from the URI.  */
  5441 
  5442   fill = (char *) vp->tree_uri;
  5443 
  5444   if (strncmp (fill, "content://", 10))
  5445     emacs_abort ();
  5446 
  5447   /* Skip the content header.  */
  5448   fill += sizeof "content://" - 1;
  5449 
  5450   /* The authority segment of the URI is between here and the
  5451      next slash.  */
  5452 
  5453   end = strchr (fill, '/');
  5454 
  5455   if (!end)
  5456     emacs_abort ();
  5457 
  5458   if (end - fill >= PATH_MAX)
  5459     {
  5460       errno = ENAMETOOLONG;
  5461       xfree (dir);
  5462       return NULL;
  5463     }
  5464 
  5465   /* Copy the authority over.  */
  5466 
  5467   memcpy (component, fill, end - fill);
  5468   component[end - fill] = '\0';
  5469 
  5470   if (asprintf (&dir->name, "/content/storage/%s/%s%s",
  5471                 component, vp->tree_id, vp->name) < 0)
  5472     {
  5473       /* Out of memory.  */
  5474       xfree (dir);
  5475       memory_full (0);
  5476     }
  5477 
  5478   /* Now open a cursor that iterates through each file in this
  5479      directory.  */
  5480 
  5481   cursor = android_saf_tree_opendir_1 (vp);
  5482 
  5483   if (!cursor)
  5484     {
  5485       xfree (dir);
  5486       xfree (dir->name);
  5487       return NULL;
  5488     }
  5489 
  5490   dir->cursor = cursor;
  5491   dir->fd = -1;
  5492   dir->next = all_saf_tree_vdirs;
  5493   all_saf_tree_vdirs = dir;
  5494   return &dir->vdir;
  5495 }
  5496 
  5497 /* Create a vnode designating the file NAME within a directory tree
  5498    whose identifier is TREE.  As with all other `name' functions, NAME
  5499    may be modified.
  5500 
  5501    AUTHORITY is the name of the content provider authority that is
  5502    offering TREE.
  5503 
  5504    Value is NULL and errno is set if no document tree or provider by
  5505    those names exists, or some other error takes place (for example,
  5506    if TREE and AUTHORITY aren't encoded correctly.)  */
  5507 
  5508 static struct android_vnode *
  5509 android_saf_tree_from_name (char *name, const char *tree,
  5510                             const char *authority)
  5511 {
  5512   struct android_saf_tree_vnode root;
  5513   jobject tree_string, authority_string, result;
  5514   jmethodID method;
  5515   const char *uri;
  5516   struct android_vnode *vp;
  5517 
  5518   /* It's not a given that NAME and TREE are actually in the modified
  5519      UTF-8 format used by the JVM to encode strings, and the JVM
  5520      aborts when encountering a string that is not.  Make sure they
  5521      are valid before continuing.  */
  5522 
  5523   if (android_verify_jni_string (name)
  5524       || android_verify_jni_string (authority))
  5525     {
  5526       errno = ENOENT;
  5527       return NULL;
  5528     }
  5529 
  5530   tree_string = (*android_java_env)->NewStringUTF (android_java_env,
  5531                                                    tree);
  5532   android_exception_check ();
  5533 
  5534   authority_string
  5535     = (*android_java_env)->NewStringUTF (android_java_env,
  5536                                          authority);
  5537   android_exception_check_1 (tree_string);
  5538 
  5539   /* Now create the URI and detect if Emacs has the rights to access
  5540      it.  */
  5541 
  5542   method = service_class.get_tree_uri;
  5543   result
  5544     = (*android_java_env)->CallNonvirtualObjectMethod (android_java_env,
  5545                                                        emacs_service,
  5546                                                        service_class.class,
  5547                                                        method, tree_string,
  5548                                                        authority_string);
  5549   android_exception_check_2 (tree_string, authority_string);
  5550   ANDROID_DELETE_LOCAL_REF (tree_string);
  5551   ANDROID_DELETE_LOCAL_REF (authority_string);
  5552 
  5553   /* If it doesn't, return NULL and set errno to ENOENT.  */
  5554 
  5555   if (!result)
  5556     {
  5557       errno = ENOENT;
  5558       return NULL;
  5559     }
  5560 
  5561   /* Otherwise, decode this string.  */
  5562   uri = (*android_java_env)->GetStringUTFChars (android_java_env, result,
  5563                                                 NULL);
  5564   android_exception_check_nonnull ((void *) uri, result);
  5565 
  5566   /* Fill in root.tree_uri with values that represent the root of this
  5567      document tree.  */
  5568 
  5569   root.vnode.ops = &saf_tree_vfs_ops;
  5570   root.vnode.type = ANDROID_VNODE_SAF_TREE;
  5571   root.vnode.flags = 0;
  5572   root.tree_uri = uri;
  5573   root.tree_id = (char *) tree;
  5574   root.document_id = NULL;
  5575   root.name = (char *) "/";
  5576 
  5577   vp = (*root.vnode.ops->name) (&root.vnode, name, strlen (name));
  5578   (*android_java_env)->ReleaseStringUTFChars (android_java_env,
  5579                                               (jstring) result, uri);
  5580   ANDROID_DELETE_LOCAL_REF (result);
  5581   return vp;
  5582 }
  5583 
  5584 /* Return any open SAF tree directory stream for which dirfd has
  5585    returned the file descriptor DIRFD.  Return NULL otherwise.  */
  5586 
  5587 static struct android_saf_tree_vdir *
  5588 android_saf_tree_get_directory (int dirfd)
  5589 {
  5590   struct android_saf_tree_vdir *dir;
  5591 
  5592   for (dir = all_saf_tree_vdirs; dir; dir = dir->next)
  5593     {
  5594       if (dir->fd == dirfd && dirfd != -1)
  5595         return dir;
  5596     }
  5597 
  5598   return NULL;
  5599 }
  5600 
  5601 
  5602 
  5603 /* SAF file vnode.  The information used to uniquely identify a file
  5604    is identical to that used to identify an SAF directory, but the
  5605    vnode operations are different.  */
  5606 
  5607 /* Define `struct android_saf_file_vnode' to be identical to a file
  5608    vnode.  */
  5609 
  5610 #define android_saf_file_vnode android_saf_tree_vnode
  5611 
  5612 /* Structure describing an open ParcelFileDescriptor.  */
  5613 
  5614 struct android_parcel_fd
  5615 {
  5616   /* The next open parcel file descriptor.  */
  5617   struct android_parcel_fd *next;
  5618 
  5619   /* Global reference to this parcel file descriptor.  */
  5620   jobject descriptor;
  5621 
  5622   /* The modification time of this parcel file descriptor, or
  5623      `invalid_timespec'.  */
  5624   struct timespec mtime;
  5625 
  5626   /* The file descriptor itself.  */
  5627   int fd;
  5628 };
  5629 
  5630 static struct android_vnode *android_saf_file_name (struct android_vnode *,
  5631                                                     char *, size_t);
  5632 static int android_saf_file_open (struct android_vnode *, int,
  5633                                   mode_t, bool, int *, AAsset **);
  5634 static int android_saf_file_unlink (struct android_vnode *);
  5635 static int android_saf_file_rmdir (struct android_vnode *);
  5636 static struct android_vdir *android_saf_file_opendir (struct android_vnode *);
  5637 
  5638 /* Vector of VFS operations associated with SAF tree VFS nodes.  */
  5639 
  5640 static struct android_vops saf_file_vfs_ops =
  5641   {
  5642     android_saf_file_name,
  5643     android_saf_file_open,
  5644     android_saf_tree_close,
  5645     android_saf_file_unlink,
  5646     android_saf_tree_symlink,
  5647     android_saf_file_rmdir,
  5648     android_saf_tree_rename,
  5649     android_saf_tree_stat,
  5650     android_saf_tree_access,
  5651     android_saf_tree_mkdir,
  5652     android_saf_tree_chmod,
  5653     android_saf_tree_readlink,
  5654     android_saf_file_opendir,
  5655   };
  5656 
  5657 /* Chain of all parcel file descriptors currently open.  */
  5658 static struct android_parcel_fd *open_parcel_fds;
  5659 
  5660 static struct android_vnode *
  5661 android_saf_file_name (struct android_vnode *vnode, char *name,
  5662                        size_t length)
  5663 {
  5664   struct android_saf_file_vnode *vp;
  5665 
  5666   /* If LENGTH is empty, make a copy of this vnode and return it.  */
  5667 
  5668   if (length < 1)
  5669     {
  5670       vp = xmalloc (sizeof *vp);
  5671       memcpy (vp, vnode, sizeof *vp);
  5672 
  5673       /* Duplicate the information contained within VNODE.  */
  5674 
  5675       vp->tree_uri = xstrdup (vp->tree_uri);
  5676       vp->tree_id = xstrdup (vp->tree_id);
  5677       vp->name = xstrdup (vp->name);
  5678       vp->document_id = xstrdup (vp->name);
  5679 
  5680       return &vp->vnode;
  5681     }
  5682 
  5683   /* A file vnode has no children of its own.  */
  5684   errno = ENOTDIR;
  5685   return NULL;
  5686 }
  5687 
  5688 static int
  5689 android_saf_file_open (struct android_vnode *vnode, int flags,
  5690                        mode_t mode, bool asset_p, int *fd_return,
  5691                        AAsset **asset)
  5692 {
  5693   struct android_saf_file_vnode *vp;
  5694   jobject uri, id, descriptor;
  5695   jmethodID method;
  5696   jboolean read, trunc, write;
  5697   jint fd;
  5698   struct android_parcel_fd *info;
  5699   struct stat statb;
  5700 
  5701   if (inside_saf_critical_section)
  5702     {
  5703       errno = EIO;
  5704       return -1;
  5705     }
  5706 
  5707   /* O_APPEND isn't supported as a consequence of Android content
  5708      providers defaulting to truncating the file.  */
  5709 
  5710   if (flags & O_APPEND)
  5711     {
  5712       errno = EOPNOTSUPP;
  5713       return -1;
  5714     }
  5715 
  5716   /* Build strings for both the URI and ID.  */
  5717 
  5718   vp = (struct android_saf_file_vnode *) vnode;
  5719   uri = (*android_java_env)->NewStringUTF (android_java_env,
  5720                                            vp->tree_uri);
  5721   android_exception_check ();
  5722   id = (*android_java_env)->NewStringUTF (android_java_env,
  5723                                           vp->document_id);
  5724   android_exception_check_1 (uri);
  5725 
  5726   /* Open a parcel file descriptor according to flags.  Documentation
  5727      for the SAF openDocument operation is scant and seldom helpful.
  5728      From observations made, it is clear that their file access modes
  5729      are inconsistently implemented, and that at least:
  5730 
  5731        r   = either an FIFO or a real file, without truncation.
  5732        w   = either an FIFO or a real file, with OR without truncation.
  5733        wt  = either an FIFO or a real file, with truncation.
  5734        rw  = a real file, without truncation.
  5735        rwt = a real file, with truncation.
  5736 
  5737      This diverges from the self-contradicting documentation, where
  5738      openDocument says nothing about truncation, and openFile mentions
  5739      that w can elect not to truncate and programs which rely on
  5740      truncation should use wt.
  5741 
  5742      Since Emacs is prepared to handle FIFOs within fileio.c, simply
  5743      specify the straightforward relationship between FLAGS and the
  5744      file access modes listed above.  */
  5745 
  5746   method = service_class.open_document;
  5747   read = trunc = write = false;
  5748 
  5749   if ((flags & O_RDWR) == O_RDWR || (flags & O_WRONLY))
  5750     write = true;
  5751 
  5752   if (flags & O_TRUNC)
  5753     trunc = true;
  5754 
  5755   if ((flags & O_RDWR) == O_RDWR || !write)
  5756     read = true;
  5757 
  5758   inside_saf_critical_section = true;
  5759   descriptor
  5760     = (*android_java_env)->CallNonvirtualObjectMethod (android_java_env,
  5761                                                        emacs_service,
  5762                                                        service_class.class,
  5763                                                        method, uri, id,
  5764                                                        read, write, trunc);
  5765   inside_saf_critical_section = false;
  5766 
  5767   if (android_saf_exception_check (2, uri, id))
  5768     return -1;
  5769 
  5770   ANDROID_DELETE_LOCAL_REF (uri);
  5771   ANDROID_DELETE_LOCAL_REF (id);
  5772 
  5773   if (!descriptor)
  5774     {
  5775       /* Assume that permission has been denied if DESCRIPTOR cannot
  5776          be opened.  */
  5777       errno = EPERM;
  5778       return -1;
  5779     }
  5780 
  5781   /* Allocate a record for this file descriptor.  Parcel file
  5782      descriptors should be closed using their own `close' function,
  5783      which takes care of notifying the source that it has been
  5784      closed.  */
  5785   info = xmalloc (sizeof *info);
  5786 
  5787   /* Now obtain the file descriptor.  */
  5788   fd = (*android_java_env)->CallIntMethod (android_java_env,
  5789                                            descriptor,
  5790                                            fd_class.get_fd);
  5791   android_exception_check_1 (descriptor);
  5792 
  5793   /* Create a global reference to descriptor.  */
  5794   info->descriptor
  5795     = (*android_java_env)->NewGlobalRef (android_java_env,
  5796                                          descriptor);
  5797 
  5798   if (!info->descriptor)
  5799     {
  5800       /* If the global reference can't be created, delete
  5801          descriptor.  */
  5802       (*android_java_env)->ExceptionClear (android_java_env);
  5803       (*android_java_env)->CallVoidMethod (android_java_env,
  5804                                            descriptor,
  5805                                            fd_class.close);
  5806       (*android_java_env)->ExceptionClear (android_java_env);
  5807       ANDROID_DELETE_LOCAL_REF (descriptor);
  5808 
  5809       /* Free INFO.  */
  5810       xfree (info);
  5811 
  5812       /* Set errno to EMFILE and return.  */
  5813       errno = EMFILE;
  5814       return -1;
  5815     }
  5816 
  5817   /* Delete the local ref to DESCRIPTOR.  */
  5818   ANDROID_DELETE_LOCAL_REF (descriptor);
  5819 
  5820   /* Try to retrieve the modification time of this file from the
  5821      content provider.
  5822 
  5823      Refrain from introducing the file status into the file status
  5824      cache if FLAGS & O_RDWR or FLAGS & O_WRONLY: the cached file
  5825      status will contain a size and modification time inconsistent
  5826      with the result of any modifications that later transpire.  */
  5827 
  5828   if (!android_saf_stat (vp->tree_uri, vp->document_id,
  5829                          &statb, write))
  5830     info->mtime = get_stat_mtime (&statb);
  5831   else
  5832     info->mtime = invalid_timespec ();
  5833 
  5834   /* Set info->fd and chain it onto the list.  */
  5835   info->fd = fd;
  5836   info->next = open_parcel_fds;
  5837   open_parcel_fds = info;
  5838 
  5839   /* Return the file descriptor.  */
  5840   *fd_return = fd;
  5841   return 0;
  5842 }
  5843 
  5844 static int
  5845 android_saf_file_unlink (struct android_vnode *vnode)
  5846 {
  5847   struct android_saf_file_vnode *vp;
  5848 
  5849   vp = (struct android_saf_file_vnode *) vnode;
  5850   return android_saf_delete_document (vp->tree_uri,
  5851                                       vp->document_id,
  5852                                       vp->name);
  5853 }
  5854 
  5855 static int
  5856 android_saf_file_rmdir (struct android_vnode *vnode)
  5857 {
  5858   errno = ENOTDIR;
  5859   return -1;
  5860 }
  5861 
  5862 static struct android_vdir *
  5863 android_saf_file_opendir (struct android_vnode *vnode)
  5864 {
  5865   errno = ENOTDIR;
  5866   return NULL;
  5867 }
  5868 
  5869 /* Close FD if it's a parcel file descriptor and return true.
  5870    If FD isn't, return false.
  5871 
  5872    Such file descriptors need to be closed using a function
  5873    written in Java, to tell the sender that it has been
  5874    closed.  */
  5875 
  5876 static bool
  5877 android_close_parcel_fd (int fd)
  5878 {
  5879   struct android_parcel_fd *tem, **next, *temp;
  5880 
  5881   for (next = &open_parcel_fds; (tem = *next);)
  5882     {
  5883       if (tem->fd == fd)
  5884         {
  5885           (*android_java_env)->CallVoidMethod (android_java_env,
  5886                                                tem->descriptor,
  5887                                                fd_class.close);
  5888 
  5889           /* Ignore exceptions for the same reason EINTR errors from
  5890              `close' should be ignored.  */
  5891           (*android_java_env)->ExceptionClear (android_java_env);
  5892           (*android_java_env)->DeleteGlobalRef (android_java_env,
  5893                                                 tem->descriptor);
  5894 
  5895           temp = tem->next;
  5896           xfree (tem);
  5897           *next = temp;
  5898 
  5899           return true;
  5900         }
  5901       else
  5902         next = &(*next)->next;
  5903     }
  5904 
  5905   return false;
  5906 }
  5907 
  5908 
  5909 
  5910 /* SAF ``new'' vnodes.  These nodes share their data structures
  5911    with tree and file vnodes, but represent files that don't actually
  5912    exist within a directory.  In them, the document ID represents not
  5913    the file designated by the vnode itself, but rather its parent
  5914    directory.
  5915 
  5916    The only vops defined serve to create directories or files, at
  5917    which point the vnode becomes invalid.  */
  5918 
  5919 #define android_saf_new_vnode android_saf_tree_vnode
  5920 
  5921 static struct android_vnode *android_saf_new_name (struct android_vnode *,
  5922                                                    char *, size_t);
  5923 static int android_saf_new_open (struct android_vnode *, int,
  5924                                  mode_t, bool, int *, AAsset **);
  5925 static int android_saf_new_unlink (struct android_vnode *);
  5926 static int android_saf_new_symlink (const char *, struct android_vnode *);
  5927 static int android_saf_new_rmdir (struct android_vnode *);
  5928 static int android_saf_new_rename (struct android_vnode *,
  5929                                    struct android_vnode *, bool);
  5930 static int android_saf_new_stat (struct android_vnode *, struct stat *);
  5931 static int android_saf_new_access (struct android_vnode *, int);
  5932 static int android_saf_new_mkdir (struct android_vnode *, mode_t);
  5933 static int android_saf_new_chmod (struct android_vnode *, mode_t, int);
  5934 static ssize_t android_saf_new_readlink (struct android_vnode *, char *,
  5935                                          size_t);
  5936 static struct android_vdir *android_saf_new_opendir (struct android_vnode *);
  5937 
  5938 /* Vector of VFS operations associated with SAF new VFS nodes.  */
  5939 
  5940 static struct android_vops saf_new_vfs_ops =
  5941   {
  5942     android_saf_new_name,
  5943     android_saf_new_open,
  5944     android_saf_tree_close,
  5945     android_saf_new_unlink,
  5946     android_saf_new_symlink,
  5947     android_saf_new_rmdir,
  5948     android_saf_new_rename,
  5949     android_saf_new_stat,
  5950     android_saf_new_access,
  5951     android_saf_new_mkdir,
  5952     android_saf_new_chmod,
  5953     android_saf_new_readlink,
  5954     android_saf_new_opendir,
  5955   };
  5956 
  5957 static struct android_vnode *
  5958 android_saf_new_name (struct android_vnode *vnode, char *name,
  5959                       size_t length)
  5960 {
  5961   struct android_saf_new_vnode *vp;
  5962 
  5963   /* If LENGTH is empty, make a copy of this vnode and return it.  */
  5964 
  5965   if (length < 1)
  5966     {
  5967       vp = xmalloc (sizeof *vp);
  5968       memcpy (vp, vnode, sizeof *vp);
  5969 
  5970       /* Duplicate the information contained within VNODE.  */
  5971 
  5972       vp->tree_uri = xstrdup (vp->tree_uri);
  5973       vp->tree_id = xstrdup (vp->tree_id);
  5974       vp->name = xstrdup (vp->name);
  5975       vp->document_id = xstrdup (vp->name);
  5976 
  5977       return &vp->vnode;
  5978     }
  5979 
  5980   /* A nonexistent vnode has no children of its own.  */
  5981   errno = ENOTDIR;
  5982   return NULL;
  5983 }
  5984 
  5985 static int
  5986 android_saf_new_open (struct android_vnode *vnode, int flags,
  5987                       mode_t mode, bool asset_p, int *fd_return,
  5988                       AAsset **asset)
  5989 {
  5990   struct android_saf_new_vnode *vp;
  5991   char *end;
  5992   jstring name, id, uri, new_id;
  5993   const char *new_doc_id;
  5994   jmethodID method;
  5995 
  5996   /* If creating a file wasn't intended, return ENOENT.  */
  5997 
  5998   if (!(flags & O_CREAT))
  5999     {
  6000       errno = ENOENT;
  6001       return -1;
  6002     }
  6003 
  6004   /* If vp->name indicates that it's a directory, return ENOENT.  */
  6005 
  6006   vp = (struct android_saf_new_vnode *) vnode;
  6007   end = strrchr (vp->name, '/');
  6008 
  6009   /* VP->name must contain at least one directory separator.  */
  6010   eassert (end);
  6011 
  6012   if (end[1] == '\0')
  6013     {
  6014       errno = ENOENT;
  6015       return -1;
  6016     }
  6017 
  6018   /* Otherwise, try to create a new document.  First, build strings
  6019      for the name, ID and document URI.  */
  6020 
  6021   name = (*android_java_env)->NewStringUTF (android_java_env,
  6022                                             end + 1);
  6023   android_exception_check ();
  6024   id = (*android_java_env)->NewStringUTF (android_java_env,
  6025                                           vp->document_id);
  6026   android_exception_check_1 (name);
  6027   uri = (*android_java_env)->NewStringUTF (android_java_env,
  6028                                            vp->tree_uri);
  6029   android_exception_check_2 (name, id);
  6030 
  6031   /* Next, try to create a new document and retrieve its ID.  */
  6032 
  6033   method = service_class.create_document;
  6034   new_id = (*android_java_env)->CallNonvirtualObjectMethod (android_java_env,
  6035                                                             emacs_service,
  6036                                                             service_class.class,
  6037                                                             method, uri, id,
  6038                                                             name);
  6039 
  6040   if (android_saf_exception_check (3, name, id, uri))
  6041     return -1;
  6042 
  6043   /* Delete unused local references.  */
  6044   ANDROID_DELETE_LOCAL_REF (name);
  6045   ANDROID_DELETE_LOCAL_REF (id);
  6046   ANDROID_DELETE_LOCAL_REF (uri);
  6047 
  6048   if (!new_id)
  6049     {
  6050       /* The file couldn't be created for some reason.  */
  6051       errno = EIO;
  6052       return -1;
  6053     }
  6054 
  6055   /* Now, free VP->document_id and replace it with the service
  6056      document ID.  */
  6057 
  6058   new_doc_id = (*android_java_env)->GetStringUTFChars (android_java_env,
  6059                                                        new_id, NULL);
  6060   android_exception_check_nonnull ((void *) new_doc_id, new_id);
  6061 
  6062   xfree (vp->document_id);
  6063   vp->document_id = xstrdup (new_doc_id);
  6064 
  6065   (*android_java_env)->ReleaseStringUTFChars (android_java_env,
  6066                                               new_id, new_doc_id);
  6067   ANDROID_DELETE_LOCAL_REF (new_id);
  6068 
  6069   /* Finally, transform this vnode into a file vnode and call its
  6070      `open' function.  */
  6071   vp->vnode.type = ANDROID_VNODE_SAF_FILE;
  6072   vp->vnode.ops = &saf_file_vfs_ops;
  6073   return (*vp->vnode.ops->open) (vnode, flags, mode, asset_p,
  6074                                  fd_return, asset);
  6075 }
  6076 
  6077 static int
  6078 android_saf_new_unlink (struct android_vnode *vnode)
  6079 {
  6080   errno = ENOENT;
  6081   return -1;
  6082 }
  6083 
  6084 static int
  6085 android_saf_new_symlink (const char *target, struct android_vnode *vnode)
  6086 {
  6087   errno = EPERM;
  6088   return -1;
  6089 }
  6090 
  6091 static int
  6092 android_saf_new_rmdir (struct android_vnode *vnode)
  6093 {
  6094   errno = ENOENT;
  6095   return -1;
  6096 }
  6097 
  6098 static int
  6099 android_saf_new_rename (struct android_vnode *src,
  6100                         struct android_vnode *dst,
  6101                         bool keep_existing)
  6102 {
  6103   errno = ENOENT;
  6104   return -1;
  6105 }
  6106 
  6107 static int
  6108 android_saf_new_stat (struct android_vnode *vnode,
  6109                       struct stat *statb)
  6110 {
  6111   errno = ENOENT;
  6112   return -1;
  6113 }
  6114 
  6115 static int
  6116 android_saf_new_access (struct android_vnode *vnode, int mode)
  6117 {
  6118   if (mode != F_OK && !(mode & (W_OK | X_OK | R_OK)))
  6119     errno = EINVAL;
  6120   else
  6121     errno = ENOENT;
  6122 
  6123   return -1;
  6124 }
  6125 
  6126 static int
  6127 android_saf_new_mkdir (struct android_vnode *vnode, mode_t mode)
  6128 {
  6129   struct android_saf_new_vnode *vp;
  6130   jstring name, id, uri, new_id;
  6131   jmethodID method;
  6132   const char *new_doc_id;
  6133   char *end;
  6134 
  6135   vp = (struct android_saf_tree_vnode *) vnode;
  6136 
  6137   /* Find the last component of vp->name.  */
  6138   end = strrchr (vp->name, '/');
  6139 
  6140   /* VP->name must contain at least one directory separator.  */
  6141   eassert (end);
  6142 
  6143   if (end[1] == '\0')
  6144     {
  6145       /* There's a trailing directory separator.  Search
  6146          backwards.  */
  6147 
  6148       end--;
  6149       while (end != vp->name && *end != '/')
  6150         end--;
  6151 
  6152       /* vp->name[0] is always a directory separator.  */
  6153       eassert (*end == '/');
  6154     }
  6155 
  6156   /* Otherwise, try to create a new document.  First, build strings
  6157      for the name, ID and document URI.  */
  6158 
  6159   name = (*android_java_env)->NewStringUTF (android_java_env,
  6160                                             end + 1);
  6161   android_exception_check ();
  6162   id = (*android_java_env)->NewStringUTF (android_java_env,
  6163                                           vp->document_id);
  6164   android_exception_check_1 (name);
  6165   uri = (*android_java_env)->NewStringUTF (android_java_env,
  6166                                            vp->tree_uri);
  6167   android_exception_check_2 (name, id);
  6168 
  6169   /* Next, try to create a new document and retrieve its ID.  */
  6170 
  6171   method = service_class.create_directory;
  6172   new_id = (*android_java_env)->CallNonvirtualObjectMethod (android_java_env,
  6173                                                             emacs_service,
  6174                                                             service_class.class,
  6175                                                             method, uri, id,
  6176                                                             name);
  6177 
  6178   if (android_saf_exception_check (3, name, id, uri))
  6179     return -1;
  6180 
  6181   /* Delete unused local references.  */
  6182   ANDROID_DELETE_LOCAL_REF (name);
  6183   ANDROID_DELETE_LOCAL_REF (id);
  6184   ANDROID_DELETE_LOCAL_REF (uri);
  6185 
  6186   if (!new_id)
  6187     {
  6188       /* The file couldn't be created for some reason.  */
  6189       errno = EIO;
  6190       return -1;
  6191     }
  6192 
  6193   /* Now, free VP->document_id and replace it with the service
  6194      document ID.  */
  6195 
  6196   new_doc_id = (*android_java_env)->GetStringUTFChars (android_java_env,
  6197                                                        new_id, NULL);
  6198 
  6199   if (android_saf_exception_check (3, name, id, uri))
  6200     return -1;
  6201 
  6202   xfree (vp->document_id);
  6203   vp->document_id = xstrdup (new_doc_id);
  6204 
  6205   (*android_java_env)->ReleaseStringUTFChars (android_java_env,
  6206                                               new_id, new_doc_id);
  6207   ANDROID_DELETE_LOCAL_REF (new_id);
  6208 
  6209   /* Finally, transform this vnode into a directory vnode.  */
  6210   vp->vnode.type = ANDROID_VNODE_SAF_TREE;
  6211   vp->vnode.ops = &saf_tree_vfs_ops;
  6212   return 0;
  6213 }
  6214 
  6215 static int
  6216 android_saf_new_chmod (struct android_vnode *vnode, mode_t mode,
  6217                        int flags)
  6218 {
  6219   errno = ENOENT;
  6220   return -1;
  6221 }
  6222 
  6223 static ssize_t
  6224 android_saf_new_readlink (struct android_vnode *vnode, char *buffer,
  6225                           size_t size)
  6226 {
  6227   errno = ENOENT;
  6228   return -1;
  6229 }
  6230 
  6231 static struct android_vdir *
  6232 android_saf_new_opendir (struct android_vnode *vnode)
  6233 {
  6234   errno = ENOENT;
  6235   return NULL;
  6236 }
  6237 
  6238 
  6239 
  6240 /* Synchronization between SAF and Emacs.  Consult EmacsSafThread.java
  6241    for more details.  */
  6242 
  6243 /* Semaphore posted upon the completion of an SAF operation.  */
  6244 static sem_t saf_completion_sem;
  6245 
  6246 #ifdef __clang__
  6247 #pragma clang diagnostic push
  6248 #pragma clang diagnostic ignored "-Wmissing-prototypes"
  6249 #else /* GNUC */
  6250 #pragma GCC diagnostic push
  6251 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
  6252 #endif /* __clang__ */
  6253 
  6254 JNIEXPORT jint JNICALL
  6255 NATIVE_NAME (safSyncAndReadInput) (JNIEnv *env, jobject object)
  6256 {
  6257   while (sem_wait (&saf_completion_sem) < 0)
  6258     {
  6259       if (input_blocked_p ())
  6260         continue;
  6261 
  6262       process_pending_signals ();
  6263 
  6264       if (!NILP (Vquit_flag))
  6265         {
  6266           __android_log_print (ANDROID_LOG_VERBOSE, __func__,
  6267                                "quitting from IO operation");
  6268           return 1;
  6269         }
  6270     }
  6271 
  6272   return 0;
  6273 }
  6274 
  6275 JNIEXPORT void JNICALL
  6276 NATIVE_NAME (safSync) (JNIEnv *env, jobject object)
  6277 {
  6278   while (sem_wait (&saf_completion_sem) < 0)
  6279     process_pending_signals ();
  6280 }
  6281 
  6282 JNIEXPORT void JNICALL
  6283 NATIVE_NAME (safPostRequest) (JNIEnv *env, jobject object)
  6284 {
  6285   sem_post (&saf_completion_sem);
  6286 }
  6287 
  6288 JNIEXPORT jboolean JNICALL
  6289 NATIVE_NAME (ftruncate) (JNIEnv *env, jobject object, jint fd)
  6290 {
  6291   if (ftruncate (fd, 0) < 0)
  6292     return false;
  6293 
  6294   /* Reset the file pointer.  */
  6295   if (lseek (fd, 0, SEEK_SET) < 0)
  6296     return false;
  6297 
  6298   return true;
  6299 }
  6300 
  6301 #ifdef __clang__
  6302 #pragma clang diagnostic pop
  6303 #else /* GNUC */
  6304 #pragma GCC diagnostic pop
  6305 #endif /* __clang__ */
  6306 
  6307 
  6308 
  6309 /* Root vnode.  This vnode represents the root inode, and is a regular
  6310    Unix vnode with modifications to `name' that make it return asset
  6311    vnodes.  */
  6312 
  6313 static struct android_vnode *android_root_name (struct android_vnode *,
  6314                                                 char *, size_t);
  6315 
  6316 /* Vector of VFS operations associated with Unix root filesystem VFS
  6317    nodes.  */
  6318 
  6319 static struct android_vops root_vfs_ops =
  6320   {
  6321     android_root_name,
  6322     android_unix_open,
  6323     android_unix_close,
  6324     android_unix_unlink,
  6325     android_unix_symlink,
  6326     android_unix_rmdir,
  6327     android_unix_rename,
  6328     android_unix_stat,
  6329     android_unix_access,
  6330     android_unix_mkdir,
  6331     android_unix_chmod,
  6332     android_unix_readlink,
  6333     android_unix_opendir,
  6334   };
  6335 
  6336 /* Array of special named vnodes.  */
  6337 
  6338 static struct android_special_vnode special_vnodes[] =
  6339   {
  6340     { "assets",  6, android_afs_initial,        },
  6341     { "content", 7, android_content_initial,    },
  6342   };
  6343 
  6344 static struct android_vnode *
  6345 android_root_name (struct android_vnode *vnode, char *name,
  6346                    size_t length)
  6347 {
  6348   char *component_end;
  6349   struct android_special_vnode *special;
  6350   size_t i;
  6351 
  6352   /* Skip any leading separator in NAME.  */
  6353 
  6354   if (*name == '/')
  6355     name++, length--;
  6356 
  6357   /* Look for the first directory separator.  */
  6358   component_end = strchr (name, '/');
  6359 
  6360   /* If not there, use name + length.  */
  6361 
  6362   if (!component_end)
  6363     component_end = name + length;
  6364   else
  6365     /* Move past the spearator character.  */
  6366     component_end++;
  6367 
  6368   /* Now, find out if the first component is a special vnode; if so,
  6369      call its root lookup function with the rest of NAME there.  */
  6370 
  6371   for (i = 0; i < ARRAYELTS (special_vnodes); ++i)
  6372     {
  6373       special = &special_vnodes[i];
  6374 
  6375       if (component_end - name == special->length
  6376           && !memcmp (special->name, name, special->length))
  6377         return (*special->initial) (component_end,
  6378                                     length - special->length);
  6379 
  6380       /* Detect the case where a special is named with a trailing
  6381          directory separator.  */
  6382 
  6383       if (component_end - name == special->length + 1
  6384           && !memcmp (special->name, name, special->length)
  6385           && name[special->length] == '/')
  6386         /* Make sure to include the directory separator.  */
  6387         return (*special->initial) (component_end - 1,
  6388                                     length - special->length);
  6389     }
  6390 
  6391   /* Otherwise, continue searching for a vnode normally.  */
  6392   return android_unix_name (vnode, name, length);
  6393 }
  6394 
  6395 
  6396 
  6397 /* File system lookup.  */
  6398 
  6399 /* Look up the vnode that designates NAME, a file name that is at
  6400    least N bytes.
  6401 
  6402    NAME may be either an absolute file name or a name relative to the
  6403    current working directory.  It must not be longer than PATH_MAX
  6404    bytes.
  6405 
  6406    Value is NULL upon failure with errno set accordingly, or the
  6407    vnode.  */
  6408 
  6409 static struct android_vnode *
  6410 android_name_file (const char *name)
  6411 {
  6412   char buffer[PATH_MAX + 1], *head;
  6413   const char *end;
  6414   size_t len;
  6415   int nslash, c;
  6416   struct android_vnode *vp;
  6417 
  6418   len = strlen (name);
  6419   if (len > PATH_MAX)
  6420     {
  6421       errno = ENAMETOOLONG;
  6422       return NULL;
  6423     }
  6424 
  6425   /* Now, try to ``normalize'' the file name by removing consecutive
  6426      slash characters while copying it to BUFFER.  */
  6427 
  6428   head = buffer;
  6429   nslash = 0;
  6430   for (end = name + len; name < end; ++name)
  6431     {
  6432       c = *name;
  6433 
  6434       switch (c)
  6435         {
  6436         case '/':
  6437           /* This is a directory separator character.  Two consecutive
  6438              separator characters should be replaced by a single
  6439              character; more than three in a row means that the
  6440              section of the file name before the last slash character
  6441              should be discarded.  */
  6442 
  6443           if (!nslash)
  6444             *head++ = '/';
  6445 
  6446           nslash++;
  6447 
  6448           if (nslash >= 3)
  6449             /* Return to the root directory.  */
  6450             head = buffer, *head++ = '/', nslash = 0;
  6451           break;
  6452 
  6453         default:
  6454           /* Otherwise, copy the file name over.  */
  6455           nslash = 0;
  6456           *head++ = *name;
  6457           break;
  6458         }
  6459     }
  6460 
  6461   /* Terminate the file name.  */
  6462   *head = '\0';
  6463 
  6464   /* If HEAD is a relative file name, it can't reside inside the
  6465      virtual mounts; create a Unix vnode instead.  */
  6466 
  6467   if (head == buffer || buffer[0] != '/')
  6468     return android_unix_vnode (buffer);
  6469 
  6470   /* Start looking from the root vnode.  */
  6471   vp = &root_vnode.vnode;
  6472 
  6473   /* If buffer is empty, this will create a duplicate of the root
  6474      vnode.  */
  6475   return (*vp->ops->name) (vp, buffer + 1, head - buffer - 1);
  6476 }
  6477 
  6478 
  6479 
  6480 /* Initialize the virtual filesystem layer.  Load the directory tree
  6481    from the given asset MANAGER (which should be a local reference
  6482    within ENV) that will be used to access assets in the future, and
  6483    create the root vnode.
  6484 
  6485    ENV should be a JNI environment valid for future calls to VFS
  6486    functions.  */
  6487 
  6488 void
  6489 android_vfs_init (JNIEnv *env, jobject manager)
  6490 {
  6491   jclass old;
  6492 
  6493   android_init_assets (env, manager);
  6494 
  6495   /* Create the root vnode, which is used to locate all other
  6496      vnodes.  */
  6497   root_vnode.vnode.ops = &root_vfs_ops;
  6498   root_vnode.vnode.type = ANDROID_VNODE_UNIX;
  6499   root_vnode.vnode.flags = 0;
  6500   root_vnode.name_length = 1;
  6501   root_vnode.name = (char *) "/";
  6502 
  6503   /* Initialize some required classes.  */
  6504   java_string_class = (*env)->FindClass (env, "java/lang/String");
  6505   assert (java_string_class);
  6506 
  6507   old = java_string_class;
  6508   java_string_class = (jclass) (*env)->NewGlobalRef (env,
  6509                                                      java_string_class);
  6510   assert (java_string_class);
  6511   (*env)->DeleteLocalRef (env, old);
  6512 
  6513   /* And initialize those used on Android 5.0 and later.  */
  6514 
  6515   if (android_get_current_api_level () < 21)
  6516     return;
  6517 
  6518   android_init_cursor_class (env);
  6519   android_init_entry_class (env);
  6520   android_init_fd_class (env);
  6521 
  6522   /* Initialize each of the exception classes used by
  6523      `android_saf_exception_check'.  */
  6524 
  6525   old = (*env)->FindClass (env, "java/io/FileNotFoundException");
  6526   file_not_found_exception = (*env)->NewGlobalRef (env, old);
  6527   (*env)->DeleteLocalRef (env, old);
  6528   eassert (file_not_found_exception);
  6529 
  6530   old = (*env)->FindClass (env, "java/lang/SecurityException");
  6531   security_exception = (*env)->NewGlobalRef (env, old);
  6532   (*env)->DeleteLocalRef (env, old);
  6533   eassert (security_exception);
  6534 
  6535   old = (*env)->FindClass (env, "android/os/OperationCanceledException");
  6536   operation_canceled_exception = (*env)->NewGlobalRef (env, old);
  6537   (*env)->DeleteLocalRef (env, old);
  6538   eassert (operation_canceled_exception);
  6539 
  6540   old = (*env)->FindClass (env, "java/lang/UnsupportedOperationException");
  6541   unsupported_operation_exception = (*env)->NewGlobalRef (env, old);
  6542   (*env)->DeleteLocalRef (env, old);
  6543   eassert (unsupported_operation_exception);
  6544 
  6545   old = (*env)->FindClass (env, "java/lang/OutOfMemoryError");
  6546   out_of_memory_error = (*env)->NewGlobalRef (env, old);
  6547   (*env)->DeleteLocalRef (env, old);
  6548   eassert (out_of_memory_error);
  6549 
  6550   /* Initialize the semaphore used to wait for SAF operations to
  6551      complete.  */
  6552 
  6553   if (sem_init (&saf_completion_sem, 0, 0) < 0)
  6554     emacs_abort ();
  6555 }
  6556 
  6557 /* The replacement functions that follow have several major
  6558    drawbacks:
  6559 
  6560    The first is that CWD relative file names will always be Unix
  6561    vnodes, and looking up their parents will always return another
  6562    Unix vnode.  For example, with the working directory set to
  6563    /sdcard:
  6564 
  6565      ../content/storage
  6566 
  6567    will find /sdcard/../content/storage on the Unix filesystem,
  6568    opposed to /content/storage within the ``content'' VFS.
  6569 
  6570    Emacs only uses file names expanded through `expand-file-name', so
  6571    this is unproblematic in practice.
  6572 
  6573    The second is that `..' components do not usually check that their
  6574    preceding component is a directory.  This is a side effect of their
  6575    removal from file names as part of a pre-processing step before
  6576    they are opened.  So, even if:
  6577 
  6578      /sdcard/foo.txt
  6579 
  6580    is a file, opening the directory:
  6581 
  6582      /sdcard/foo.txt/..
  6583 
  6584    will be successful.
  6585 
  6586    The third is that the handling of `..' components relative to
  6587    another vnode hasn't been tested and is only assumed to work
  6588    because the code has been written.  It does not pose a practical
  6589    problem, however, as Emacs only names files starting from the root
  6590    vnode.
  6591 
  6592    The fourth is that errno values from vnode operations don't always
  6593    reflect what the Unix system calls they emulate can return: for
  6594    example, `open' may return EIO, while trying to `mkdir' within
  6595    /content will return ENOENT instead of EROFS.  This is a
  6596    consequence of how accessing a non-existent file may fail at vnode
  6597    lookup, instead of when a vop is used.  This problem hasn't made a
  6598    sufficient nuisance of itself to justify its fix yet.
  6599 
  6600    The fifth is that trailing directory separators may be lost when
  6601    naming files relative to another vnode, as a consequence of an
  6602    optimization used to avoid allocating too much stack or heap
  6603    space.
  6604 
  6605    The sixth is that flags and other argument checking is nowhere near
  6606    exhaustive on vnode types other than Unix vnodes.
  6607 
  6608    The seventh is that certain vnode types may read async input and
  6609    return EINTR not upon the arrival of a signal itself, but instead
  6610    if subsequently read input causes Vquit_flag to be set.  These
  6611    vnodes may not be reentrant, but operating on them from within an
  6612    async input handler will at worst cause an error to be returned.
  6613 
  6614    The eight is that some vnode types do not support O_APPEND.
  6615 
  6616    And the final drawback is that directories cannot be directly
  6617    opened.  Instead, `dirfd' must be called on a directory stream used
  6618    by `openat'.
  6619 
  6620    Caveat emptor! */
  6621 
  6622 /* Open the VFS node designated by NAME, taking into account FLAGS and
  6623    MODE, both of which mean the same as they do in a call to `open'.
  6624 
  6625    Value is -1 upon failure with errno set accordingly, and a file
  6626    descriptor otherwise.  */
  6627 
  6628 int
  6629 android_open (const char *name, int flags, mode_t mode)
  6630 {
  6631   struct android_vnode *vp;
  6632   int fd, rc;
  6633 
  6634   vp = android_name_file (name);
  6635   if (!vp)
  6636     return -1;
  6637 
  6638   rc = (*vp->ops->open) (vp, flags, mode, false, &fd, NULL);
  6639   (*vp->ops->close) (vp);
  6640 
  6641   if (rc < 0)
  6642     return -1;
  6643 
  6644   /* If rc is 1, then an asset file descriptor has been returned.
  6645      This is impossible, so assert that it doesn't transpire.  */
  6646   assert (rc != 1);
  6647   return fd;
  6648 }
  6649 
  6650 /* Unlink the VFS node designated by the specified FILE.
  6651    Value is -1 upon failure with errno set, and 0 otherwise.  */
  6652 
  6653 int
  6654 android_unlink (const char *name)
  6655 {
  6656   struct android_vnode *vp;
  6657   int rc;
  6658 
  6659   vp = android_name_file (name);
  6660   if (!vp)
  6661     return -1;
  6662 
  6663   rc = (*vp->ops->unlink) (vp);
  6664   (*vp->ops->close) (vp);
  6665   return rc;
  6666 }
  6667 
  6668 /* Symlink the VFS node designated by LINKPATH to TARGET.
  6669    Value is -1 upon failure with errno set, and 0 otherwise.  */
  6670 
  6671 int
  6672 android_symlink (const char *target, const char *linkpath)
  6673 {
  6674   struct android_vnode *vp;
  6675   int rc;
  6676 
  6677   vp = android_name_file (linkpath);
  6678   if (!vp)
  6679     return -1;
  6680 
  6681   rc = (*vp->ops->symlink) (target, vp);
  6682   (*vp->ops->close) (vp);
  6683   return rc;
  6684 }
  6685 
  6686 /* Remove the empty directory at the VFS node designated by NAME.
  6687    Value is -1 upon failure with errno set, and 0 otherwise.  */
  6688 
  6689 int
  6690 android_rmdir (const char *name)
  6691 {
  6692   struct android_vnode *vp;
  6693   int rc;
  6694 
  6695   vp = android_name_file (name);
  6696   if (!vp)
  6697     return -1;
  6698 
  6699   rc = (*vp->ops->rmdir) (vp);
  6700   (*vp->ops->close) (vp);
  6701   return rc;
  6702 }
  6703 
  6704 /* Create a directory at the VFS node designated by NAME and the given
  6705    access MODE.  Value is -1 upon failure with errno set, 0
  6706    otherwise.  */
  6707 
  6708 int
  6709 android_mkdir (const char *name, mode_t mode)
  6710 {
  6711   struct android_vnode *vp;
  6712   int rc;
  6713 
  6714   vp = android_name_file (name);
  6715   if (!vp)
  6716     return -1;
  6717 
  6718   rc = (*vp->ops->mkdir) (vp, mode);
  6719   (*vp->ops->close) (vp);
  6720   return rc;
  6721 }
  6722 
  6723 /* Rename the vnode designated by SRC to the vnode designated by DST.
  6724    If DST already exists, return -1 and set errno to EEXIST.
  6725 
  6726    SRCFD and DSTFD should be AT_FDCWD, or else value is -1 and errno
  6727    is ENOSYS.
  6728 
  6729    If the filesystem or vnodes containing either DST or SRC does not
  6730    support rename operations that also check for a preexisting
  6731    destination, return -1 and set errno to ENOSYS.
  6732 
  6733    Otherwise, value and errno are identical to that of Unix
  6734    `rename' with the same arguments.  */
  6735 
  6736 int
  6737 android_renameat_noreplace (int srcfd, const char *src,
  6738                             int dstfd, const char *dst)
  6739 {
  6740   struct android_vnode *vp, *vdst;
  6741   int rc;
  6742 
  6743   if (srcfd != AT_FDCWD || dstfd != AT_FDCWD)
  6744     {
  6745       errno = ENOSYS;
  6746       return -1;
  6747     }
  6748 
  6749   /* Find vnodes for both src and dst.  */
  6750 
  6751   vp = android_name_file (src);
  6752   if (!vp)
  6753     goto error;
  6754 
  6755   vdst = android_name_file (dst);
  6756   if (!vdst)
  6757     goto error1;
  6758 
  6759   /* Now try to rename vp to vdst.  */
  6760   rc = (*vp->ops->rename) (vp, vdst, true);
  6761   (*vp->ops->close) (vp);
  6762   (*vdst->ops->close) (vdst);
  6763   return rc;
  6764 
  6765  error1:
  6766   (*vp->ops->close) (vp);
  6767  error:
  6768   return -1;
  6769 }
  6770 
  6771 /* Like `android_renameat_noreplace', but don't check for DST's
  6772    existence and don't accept placeholder SRCFD and DSTFD
  6773    arguments.  */
  6774 
  6775 int
  6776 android_rename (const char *src, const char *dst)
  6777 {
  6778   struct android_vnode *vp, *vdst;
  6779   int rc;
  6780 
  6781   /* Find vnodes for both src and dst.  */
  6782 
  6783   vp = android_name_file (src);
  6784   if (!vp)
  6785     goto error;
  6786 
  6787   vdst = android_name_file (dst);
  6788   if (!vdst)
  6789     goto error1;
  6790 
  6791   /* Now try to rename vp to vdst.  */
  6792   rc = (*vp->ops->rename) (vp, vdst, false);
  6793   (*vp->ops->close) (vp);
  6794   (*vdst->ops->close) (vdst);
  6795   return rc;
  6796 
  6797  error1:
  6798   (*vp->ops->close) (vp);
  6799  error:
  6800   return -1;
  6801 }
  6802 
  6803 
  6804 
  6805 /* fstat, fstatat, faccessat, close/fclose etc.  These functions are
  6806    somewhat tricky to wrap: they (at least partially) operate on file
  6807    descriptors, which sometimes provide a base directory for the
  6808    filesystem operations they perform.  VFS nodes aren't mapped to
  6809    file descriptors opened through them, which makes this troublesome.
  6810 
  6811    openat is not wrapped at all; uses are defined out when Emacs is
  6812    being built for Android.  The other functions fall back to directly
  6813    making Unix system calls when their base directory arguments are
  6814    not AT_FDCWD and no directory stream returned from
  6815    `android_opendir' ever returned that file descriptor, which is
  6816    enough to satisfy Emacs's current requirements for those functions
  6817    when a directory file descriptor is supplied.
  6818 
  6819    fclose and close are finally wrapped because they need to erase
  6820    information used to link file descriptors with file statistics from
  6821    their origins; fstat is also wrapped to take this information into
  6822    account, so that it can return correct file statistics for asset
  6823    directory files.  */
  6824 
  6825 /* Like fstat.  However, look up the asset corresponding to the file
  6826    descriptor.  If it exists, return the right information.  */
  6827 
  6828 int
  6829 android_fstat (int fd, struct stat *statb)
  6830 {
  6831   struct android_afs_open_fd *tem;
  6832   struct android_parcel_fd *parcel_fd;
  6833   int rc;
  6834 
  6835   for (tem = afs_file_descriptors; tem; tem = tem->next)
  6836     {
  6837       if (tem->fd == fd)
  6838         {
  6839           memcpy (statb, &tem->statb, sizeof *statb);
  6840           return 0;
  6841         }
  6842     }
  6843 
  6844   rc = fstat (fd, statb);
  6845 
  6846   /* Now look for a matching parcel file descriptor and use its
  6847      mtime if available.  */
  6848 
  6849   parcel_fd = open_parcel_fds;
  6850   for (; parcel_fd; parcel_fd = parcel_fd->next)
  6851     {
  6852       if (parcel_fd->fd == fd)
  6853         /* Set STATB->st_dev to a negative device number, signifying
  6854            that it's contained within a content provider.  */
  6855         statb->st_dev = -4;
  6856 
  6857       if (parcel_fd->fd == fd
  6858           && timespec_valid_p (parcel_fd->mtime))
  6859         {
  6860 #ifdef STAT_TIMESPEC
  6861           STAT_TIMESPEC (statb, st_mtim) = parcel_fd->mtime;
  6862 #else /* !STAT_TIMESPEC */
  6863           statb->st_mtime = parcel_fd->mtime.tv_sec;
  6864           statb->st_mtime_nsec = parcel_fd->mtime.tv_nsec;
  6865 #endif /* STAT_TIMESPEC */
  6866           break;
  6867         }
  6868     }
  6869 
  6870   return rc;
  6871 }
  6872 
  6873 /* If DIRFD is a file descriptor returned by `android_readdir' for a
  6874    non-Unix file stream, return FILENAME relative to the file name of
  6875    the directory represented by that stream within BUFFER, a buffer
  6876    SIZE bytes long.
  6877 
  6878    Value is 0 if a file name is returned, 1 otherwise.  */
  6879 
  6880 static int
  6881 android_fstatat_1 (int dirfd, const char *filename,
  6882                    char *restrict buffer, size_t size)
  6883 {
  6884   char *dir_name;
  6885   struct android_saf_root_vdir *vdir;
  6886   struct android_saf_tree_vdir *vdir1;
  6887 
  6888   /* Now establish whether DIRFD is a file descriptor corresponding to
  6889      an open asset directory stream.  */
  6890 
  6891   dir_name = android_afs_get_directory_name (dirfd);
  6892 
  6893   if (dir_name)
  6894     {
  6895       /* Look for PATHNAME relative to this directory within an asset
  6896          vnode.  */
  6897       snprintf (buffer, size, "/assets%s%s", dir_name,
  6898                 filename);
  6899       return 0;
  6900     }
  6901 
  6902   /* Do the same, but for /content directories instead.  */
  6903 
  6904   dir_name = android_content_get_directory_name (dirfd);
  6905 
  6906   if (dir_name)
  6907     {
  6908       /* Look for PATHNAME relative to this directory within an asset
  6909          vnode.  */
  6910       snprintf (buffer, size, "%s/%s", dir_name,
  6911                 filename);
  6912       return 0;
  6913     }
  6914 
  6915   /* And for /content/storage.  */
  6916 
  6917   vdir = android_saf_root_get_directory (dirfd);
  6918 
  6919   if (vdir)
  6920     {
  6921       if (vdir->authority)
  6922         snprintf (buffer, size, "/content/storage/%s/%s",
  6923                   vdir->authority, filename);
  6924       else
  6925         snprintf (buffer, size, "/content/storage/%s",
  6926                   filename);
  6927 
  6928       return 0;
  6929     }
  6930 
  6931   /* /content/storage/foo/... */
  6932 
  6933   vdir1 = android_saf_tree_get_directory (dirfd);
  6934 
  6935   if (vdir1)
  6936     {
  6937       snprintf (buffer, size, "%s%s", vdir1->name, filename);
  6938       return 0;
  6939     }
  6940 
  6941   return 1;
  6942 }
  6943 
  6944 /* If DIRFD is AT_FDCWD or a file descriptor returned by
  6945    `android_dirfd', or PATHNAME is an absolute file name, return the
  6946    file status of the VFS node designated by PATHNAME relative to the
  6947    VFS node corresponding to DIRFD, or relative to the current working
  6948    directory if DIRFD is AT_FDCWD.
  6949 
  6950    Otherwise, call `fstatat' with DIRFD, PATHNAME, STATBUF and
  6951    FLAGS.  */
  6952 
  6953 int
  6954 android_fstatat (int dirfd, const char *restrict pathname,
  6955                  struct stat *restrict statbuf, int flags)
  6956 {
  6957   char buffer[PATH_MAX + 1];
  6958   struct android_vnode *vp;
  6959   int rc;
  6960 
  6961   /* Emacs uses AT_SYMLINK_NOFOLLOW, but fortunately (?) DIRFD is
  6962      never known to Emacs or AT_FDCWD when it originates from a VFS
  6963      node representing a filesystem that supports symlinks.  */
  6964 
  6965   if (dirfd == AT_FDCWD || pathname[0] == '/')
  6966     goto vfs;
  6967 
  6968   /* Now establish whether DIRFD is a file descriptor corresponding to
  6969      an open VFS directory stream.  */
  6970 
  6971   if (!android_fstatat_1 (dirfd, pathname, buffer, PATH_MAX + 1))
  6972     {
  6973       pathname = buffer;
  6974       goto vfs;
  6975     }
  6976 
  6977   /* Fall back to fstatat.  */
  6978   return fstatat (dirfd, pathname, statbuf, flags);
  6979 
  6980  vfs:
  6981   vp = android_name_file (pathname);
  6982   if (!vp)
  6983     return -1;
  6984 
  6985   rc = (*vp->ops->stat) (vp, statbuf);
  6986   (*vp->ops->close) (vp);
  6987   return rc;
  6988 }
  6989 
  6990 /* Like `android_fstatat', but check file accessibility instead of
  6991    status.  */
  6992 
  6993 int
  6994 android_faccessat (int dirfd, const char *restrict pathname,
  6995                    int mode, int flags)
  6996 {
  6997   char buffer[PATH_MAX + 1];
  6998   struct android_vnode *vp;
  6999   int rc;
  7000 
  7001   /* Emacs uses AT_SYMLINK_NOFOLLOW, but fortunately (?) DIRFD is
  7002      never known to Emacs or AT_FDCWD when it originates from a VFS
  7003      node representing a filesystem that supports symlinks.  */
  7004 
  7005   if (dirfd == AT_FDCWD || pathname[0] == '/')
  7006     goto vfs;
  7007 
  7008   /* Now establish whether DIRFD is a file descriptor corresponding to
  7009      an open VFS directory stream.  */
  7010 
  7011   if (!android_fstatat_1 (dirfd, pathname, buffer, PATH_MAX + 1))
  7012     {
  7013       pathname = buffer;
  7014       goto vfs;
  7015     }
  7016 
  7017   /* Fall back to faccessat.  */
  7018   return faccessat (dirfd, pathname, mode, flags);
  7019 
  7020  vfs:
  7021   vp = android_name_file (pathname);
  7022   if (!vp)
  7023     return -1;
  7024 
  7025   rc = (*vp->ops->access) (vp, mode);
  7026   (*vp->ops->close) (vp);
  7027   return rc;
  7028 }
  7029 
  7030 /* Like `android_fstatat', but set file modes instead of
  7031    checking file status and respect FLAGS.  */
  7032 
  7033 int
  7034 android_fchmodat (int dirfd, const char *pathname, mode_t mode,
  7035                   int flags)
  7036 {
  7037   char buffer[PATH_MAX + 1];
  7038   struct android_vnode *vp;
  7039   int rc;
  7040 
  7041   if (dirfd == AT_FDCWD || pathname[0] == '/')
  7042     goto vfs;
  7043 
  7044   /* Now establish whether DIRFD is a file descriptor corresponding to
  7045      an open VFS directory stream.  */
  7046 
  7047   if (!android_fstatat_1 (dirfd, pathname, buffer, PATH_MAX + 1))
  7048     {
  7049       pathname = buffer;
  7050       goto vfs;
  7051     }
  7052 
  7053   /* Fall back to fchmodat.  */
  7054   return fchmodat (dirfd, pathname, mode, flags);
  7055 
  7056  vfs:
  7057   vp = android_name_file (pathname);
  7058   if (!vp)
  7059     return -1;
  7060 
  7061   rc = (*vp->ops->chmod) (vp, mode, flags);
  7062   (*vp->ops->close) (vp);
  7063   return rc;
  7064 }
  7065 
  7066 /* Like `android_fstatat', but return the target of any symbolic link
  7067    at PATHNAME instead of checking file status.  */
  7068 
  7069 ssize_t
  7070 android_readlinkat (int dirfd, const char *restrict pathname,
  7071                     char *restrict buf, size_t bufsiz)
  7072 {
  7073   char buffer[PATH_MAX + 1];
  7074   struct android_vnode *vp;
  7075   ssize_t rc;
  7076 
  7077   if (dirfd == AT_FDCWD || pathname[0] == '/')
  7078     goto vfs;
  7079 
  7080   /* Now establish whether DIRFD is a file descriptor corresponding to
  7081      an open VFS directory stream.  */
  7082 
  7083   if (!android_fstatat_1 (dirfd, pathname, buffer, PATH_MAX + 1))
  7084     {
  7085       pathname = buffer;
  7086       goto vfs;
  7087     }
  7088 
  7089   /* Fall back to readlinkat.  */
  7090   return readlinkat (dirfd, pathname, buf, bufsiz);
  7091 
  7092  vfs:
  7093   vp = android_name_file (pathname);
  7094   if (!vp)
  7095     return -1;
  7096 
  7097   rc = (*vp->ops->readlink) (vp, buf, bufsiz);
  7098   (*vp->ops->close) (vp);
  7099   return rc;
  7100 }
  7101 
  7102 /* Like `fdopen', but if FD is a parcel file descriptor, ``detach'' it
  7103    from the original.
  7104 
  7105    This is necessary because ownership over parcel file descriptors is
  7106    retained by the ParcelFileDescriptor objects that return them,
  7107    while file streams also require ownership over file descriptors
  7108    they are created on behalf of.
  7109 
  7110    Detaching the parcel file descriptor linked to FD consequentially
  7111    prevents the owner from being notified when it is eventually
  7112    closed, but for now that hasn't been demonstrated to be problematic
  7113    yet, as Emacs doesn't write to file streams.  */
  7114 
  7115 FILE *
  7116 android_fdopen (int fd, const char *mode)
  7117 {
  7118   struct android_parcel_fd *tem, **next, *temp;
  7119   int new_fd;
  7120 
  7121   for (next = &open_parcel_fds; (tem = *next);)
  7122     {
  7123       if (tem->fd == fd)
  7124         {
  7125           new_fd
  7126             = (*android_java_env)->CallIntMethod (android_java_env,
  7127                                                   tem->descriptor,
  7128                                                   fd_class.detach_fd);
  7129           temp = tem->next;
  7130           xfree (tem);
  7131           *next = temp;
  7132           android_exception_check ();
  7133 
  7134           /* Assert that FD (returned from `getFd') is identical to
  7135              the file descriptor returned by `detachFd'.  */
  7136 
  7137           if (fd != new_fd)
  7138             emacs_abort ();
  7139 
  7140           break;
  7141         }
  7142       else
  7143         next = &(*next)->next;
  7144     }
  7145 
  7146   return fdopen (fd, mode);
  7147 }
  7148 
  7149 /* Like close.  However, remove the file descriptor from the asset
  7150    table as well.  */
  7151 
  7152 int
  7153 android_close (int fd)
  7154 {
  7155   struct android_afs_open_fd *tem, **next, *temp;
  7156 
  7157   if (android_close_parcel_fd (fd))
  7158     return 0;
  7159 
  7160   for (next = &afs_file_descriptors; (tem = *next);)
  7161     {
  7162       if (tem->fd == fd)
  7163         {
  7164           temp = tem->next;
  7165           xfree (tem);
  7166           *next = temp;
  7167 
  7168           break;
  7169         }
  7170       else
  7171         next = &(*next)->next;
  7172     }
  7173 
  7174   return close (fd);
  7175 }
  7176 
  7177 /* Like fclose.  However, remove any information associated with
  7178    FILE's file descriptor from the asset table as well.  */
  7179 
  7180 int
  7181 android_fclose (FILE *stream)
  7182 {
  7183   int fd;
  7184   struct android_afs_open_fd *tem, **next, *temp;
  7185 
  7186   fd = fileno (stream);
  7187 
  7188   if (fd == -1)
  7189     goto skip;
  7190 
  7191   for (next = &afs_file_descriptors; (tem = *next);)
  7192     {
  7193       if (tem->fd == fd)
  7194         {
  7195           temp = tem->next;
  7196           xfree (*next);
  7197           *next = temp;
  7198 
  7199           break;
  7200         }
  7201       else
  7202         next = &(*next)->next;
  7203     }
  7204 
  7205  skip:
  7206   return fclose (stream);
  7207 }
  7208 
  7209 
  7210 
  7211 /* External asset management interface.  By using functions here
  7212    to read and write from files, Emacs can avoid opening a
  7213    shared memory file descriptor for each ``asset'' file.  */
  7214 
  7215 /* Like android_open.  However, return a structure that can
  7216    either directly hold an AAsset or a file descriptor.
  7217 
  7218    Value is the structure upon success.  Upon failure, value
  7219    consists of an uninitialized file descriptor, but its asset
  7220    field is set to -1, and errno is set accordingly.  */
  7221 
  7222 struct android_fd_or_asset
  7223 android_open_asset (const char *filename, int oflag, mode_t mode)
  7224 {
  7225   struct android_fd_or_asset fd;
  7226   AAsset *asset;
  7227   int rc;
  7228   struct android_vnode *vp;
  7229 
  7230   /* Now name this file.  */
  7231   vp = android_name_file (filename);
  7232   if (!vp)
  7233     goto failure;
  7234 
  7235   rc = (*vp->ops->open) (vp, oflag, mode, true, &fd.fd,
  7236                          &asset);
  7237   (*vp->ops->close) (vp);
  7238 
  7239   /* Upon failure, return fd with its asset field set to (void *)
  7240      -1.  */
  7241 
  7242   if (rc < 0)
  7243     {
  7244     failure:
  7245       fd.asset = (void *) -1;
  7246       fd.fd = -1;
  7247       return fd;
  7248     }
  7249 
  7250   if (rc == 1)
  7251     {
  7252       /* An asset file was returned.  Return the structure containing
  7253          an asset.  */
  7254       fd.asset = asset;
  7255       fd.fd = -1;
  7256       return fd;
  7257     }
  7258 
  7259   /* Otherwise, a file descriptor has been returned.  Set fd.asset to
  7260      NULL, signifying that it is a file descriptor.  */
  7261   fd.asset = NULL;
  7262   return fd;
  7263 }
  7264 
  7265 /* Like android_close.  However, it takes a ``file descriptor''
  7266    opened using android_open_asset.  */
  7267 
  7268 int
  7269 android_close_asset (struct android_fd_or_asset asset)
  7270 {
  7271   if (!asset.asset)
  7272     return android_close (asset.fd);
  7273 
  7274   AAsset_close (asset.asset);
  7275   return 0;
  7276 }
  7277 
  7278 /* Like `emacs_read_quit'.  However, it handles file descriptors
  7279    opened using `android_open_asset' as well.  */
  7280 
  7281 ssize_t
  7282 android_asset_read_quit (struct android_fd_or_asset asset,
  7283                          void *buffer, size_t size)
  7284 {
  7285   if (!asset.asset)
  7286     return emacs_read_quit (asset.fd, buffer, size);
  7287 
  7288   /* It doesn't seem possible to quit from inside AAsset_read,
  7289      sadly.  */
  7290   return AAsset_read (asset.asset, buffer, size);
  7291 }
  7292 
  7293 /* Like `read'.  However, it handles file descriptors opened
  7294    using `android_open_asset' as well.  */
  7295 
  7296 ssize_t
  7297 android_asset_read (struct android_fd_or_asset asset,
  7298                     void *buffer, size_t size)
  7299 {
  7300   if (!asset.asset)
  7301     return read (asset.fd, buffer, size);
  7302 
  7303   /* It doesn't seem possible to quit from inside AAsset_read,
  7304      sadly.  */
  7305   return AAsset_read (asset.asset, buffer, size);
  7306 }
  7307 
  7308 /* Like `lseek', but it handles ``file descriptors'' opened with
  7309    android_open_asset.  */
  7310 
  7311 off_t
  7312 android_asset_lseek (struct android_fd_or_asset asset, off_t off,
  7313                      int whence)
  7314 {
  7315   if (!asset.asset)
  7316     return lseek (asset.fd, off, whence);
  7317 
  7318   return AAsset_seek (asset.asset, off, whence);
  7319 }
  7320 
  7321 /* Like `fstat'.  */
  7322 
  7323 int
  7324 android_asset_fstat (struct android_fd_or_asset asset,
  7325                      struct stat *statb)
  7326 {
  7327   if (!asset.asset)
  7328     return android_fstat (asset.fd, statb);
  7329 
  7330   /* Clear statb.  */
  7331   memset (statb, 0, sizeof *statb);
  7332 
  7333   /* Set the mode.  */
  7334   statb->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH;
  7335 
  7336   /* Concoct a nonexistent device and an inode number.  */
  7337   statb->st_dev = -1;
  7338   statb->st_ino = 0;
  7339 
  7340   /* Owned by root.  */
  7341   statb->st_uid = 0;
  7342   statb->st_gid = 0;
  7343 
  7344   /* Size of the file.  */
  7345   statb->st_size = AAsset_getLength (asset.asset);
  7346   return 0;
  7347 }
  7348 
  7349 
  7350 
  7351 /* Directory listing emulation.  */
  7352 
  7353 /* Open a directory stream from the VFS node designated by NAME.
  7354    Value is NULL upon failure with errno set accordingly.  `errno' may
  7355    be set to EINTR.
  7356 
  7357    The directory stream returned holds local references to JNI objects
  7358    and shouldn't be used after the current local reference frame is
  7359    popped.  */
  7360 
  7361 struct android_vdir *
  7362 android_opendir (const char *name)
  7363 {
  7364   struct android_vnode *vp;
  7365   struct android_vdir *dir;
  7366 
  7367   vp = android_name_file (name);
  7368   if (!vp)
  7369     return NULL;
  7370 
  7371   dir = (*vp->ops->opendir) (vp);
  7372   (*vp->ops->close) (vp);
  7373   return dir;
  7374 }
  7375 
  7376 /* Like dirfd.  However, value is not a real directory file descriptor
  7377    if DIR is an asset directory.  */
  7378 
  7379 int
  7380 android_dirfd (struct android_vdir *dirp)
  7381 {
  7382   return (*dirp->dirfd) (dirp);
  7383 }
  7384 
  7385 /* Like readdir, but for VFS directory streams instead.  */
  7386 
  7387 struct dirent *
  7388 android_readdir (struct android_vdir *dirp)
  7389 {
  7390   return (*dirp->readdir) (dirp);
  7391 }
  7392 
  7393 /* Like closedir, but for VFS directory streams instead.  */
  7394 
  7395 void
  7396 android_closedir (struct android_vdir *dirp)
  7397 {
  7398   return (*dirp->closedir) (dirp);
  7399 }

/* [<][>][^][v][top][bottom][index][help] */