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

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