emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

feature/android 6d44d08e044: Isolate fchmodat within the Android VFS lay


From: Po Lu
Subject: feature/android 6d44d08e044: Isolate fchmodat within the Android VFS layer
Date: Thu, 3 Aug 2023 02:50:34 -0400 (EDT)

branch: feature/android
commit 6d44d08e044dd2a74c6ac65cedb32a8f7a4f82de
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Isolate fchmodat within the Android VFS layer
    
    * src/android.h: Update prototypes.
    * src/androidvfs.c (unix_vfs_ops, android_unix_chmod, afs_vfs_ops)
    (android_afs_chmod, content_vfs_ops, android_content_chmod)
    (authority_vfs_ops, android_authority_chmod, saf_root_vfs_ops)
    (android_saf_root_chmod, saf_tree_vfs_ops, android_saf_tree_chmod)
    (saf_file_vfs_ops, saf_new_vfs_ops, android_saf_new_chmod)
    (root_vfs_ops): Add `chmod' to the list of functions implemented
    by each vnode.
    (android_fchmodat): New function.
    * src/fileio.c (Fset_file_modes): Use `emacs_fchmodat'.
    * src/lisp.h:
    * src/sysdep.c (emacs_fchmodat): Delegate to android_fchmodat on
    Android.
---
 src/android.h    |   1 +
 src/androidvfs.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/fileio.c     |  10 +----
 src/lisp.h       |   1 +
 src/sysdep.c     |  10 +++++
 5 files changed, 139 insertions(+), 9 deletions(-)

diff --git a/src/android.h b/src/android.h
index 945bd649c18..cecdfab002f 100644
--- a/src/android.h
+++ b/src/android.h
@@ -74,6 +74,7 @@ extern int android_mkdir (const char *, mode_t);
 extern int android_renameat_noreplace (int, const char *,
                                       int, const char *);
 extern int android_rename (const char *, const char *);
+extern int android_fchmodat (int, const char *, mode_t, int);
 
 
 
diff --git a/src/androidvfs.c b/src/androidvfs.c
index e3b0b895df3..2b467bc444f 100644
--- a/src/androidvfs.c
+++ b/src/androidvfs.c
@@ -206,6 +206,12 @@ struct android_vops
   /* Make a directory designated by VNODE, like Unix `mkdir'.  */
   int (*mkdir) (struct android_vnode *, mode_t);
 
+  /* Change the access mode of the provided VNODE to MODE.  Value is
+     the same as with `chmod'.  FLAGS is passed verbatim from the call
+     to the delegating at-func, and is probably
+     AT_SYMLINK_NOFOLLOW.  */
+  int (*chmod) (struct android_vnode *, mode_t, int);
+
   /* Open the specified VNODE as a directory.
      Value is a ``directory handle'', or NULL upon failure.  */
   struct android_vdir *(*opendir) (struct android_vnode *);
@@ -616,6 +622,7 @@ static int android_unix_rename (struct android_vnode *,
 static int android_unix_stat (struct android_vnode *, struct stat *);
 static int android_unix_access (struct android_vnode *, int);
 static int android_unix_mkdir (struct android_vnode *, mode_t);
+static int android_unix_chmod (struct android_vnode *, mode_t, int);
 static struct android_vdir *android_unix_opendir (struct android_vnode *);
 
 /* Vector of VFS operations associated with Unix filesystem VFS
@@ -633,6 +640,7 @@ static struct android_vops unix_vfs_ops =
     android_unix_stat,
     android_unix_access,
     android_unix_mkdir,
+    android_unix_chmod,
     android_unix_opendir,
   };
 
@@ -878,6 +886,16 @@ android_unix_mkdir (struct android_vnode *vnode, mode_t 
mode)
   return mkdir (vp->name, mode);
 }
 
+static int
+android_unix_chmod (struct android_vnode *vnode, mode_t mode,
+                   int flags)
+{
+  struct android_unix_vnode *vp;
+
+  vp = (struct android_unix_vnode *) vnode;
+  return fchmodat (AT_FDCWD, vp->name, mode, flags);
+}
+
 static struct dirent *
 android_unix_readdir (struct android_vdir *vdir)
 {
@@ -1585,6 +1603,7 @@ static int android_afs_rename (struct android_vnode *,
 static int android_afs_stat (struct android_vnode *, struct stat *);
 static int android_afs_access (struct android_vnode *, int);
 static int android_afs_mkdir (struct android_vnode *, mode_t);
+static int android_afs_chmod (struct android_vnode *, mode_t, int);
 static struct android_vdir *android_afs_opendir (struct android_vnode *);
 
 /* Vector of VFS operations associated with asset VFS nodes.  */
@@ -1601,6 +1620,7 @@ static struct android_vops afs_vfs_ops =
     android_afs_stat,
     android_afs_access,
     android_afs_mkdir,
+    android_afs_chmod,
     android_afs_opendir,
   };
 
@@ -2109,6 +2129,14 @@ android_afs_mkdir (struct android_vnode *vnode, mode_t 
mode)
   return -1;
 }
 
+static int
+android_afs_chmod (struct android_vnode *vnode, mode_t mode,
+                  int flags)
+{
+  errno = EROFS;
+  return -1;
+}
+
 static struct dirent *
 android_afs_readdir (struct android_vdir *vdir)
 {
@@ -2348,6 +2376,7 @@ static int android_content_rename (struct android_vnode *,
 static int android_content_stat (struct android_vnode *, struct stat *);
 static int android_content_access (struct android_vnode *, int);
 static int android_content_mkdir (struct android_vnode *, mode_t);
+static int android_content_chmod (struct android_vnode *, mode_t, int);
 static struct android_vdir *android_content_opendir (struct android_vnode *);
 
 /* Vector of VFS operations associated with the content VFS node.  */
@@ -2364,6 +2393,7 @@ static struct android_vops content_vfs_ops =
     android_content_stat,
     android_content_access,
     android_content_mkdir,
+    android_content_chmod,
     android_content_opendir,
   };
 
@@ -2571,6 +2601,14 @@ android_content_mkdir (struct android_vnode *vnode, 
mode_t mode)
   return 0;
 }
 
+static int
+android_content_chmod (struct android_vnode *vnode, mode_t mode,
+                      int flags)
+{
+  errno = EACCES;
+  return 0;
+}
+
 static struct dirent *
 android_content_readdir (struct android_vdir *vdir)
 {
@@ -2823,6 +2861,7 @@ static int android_authority_rename (struct android_vnode 
*,
 static int android_authority_stat (struct android_vnode *, struct stat *);
 static int android_authority_access (struct android_vnode *, int);
 static int android_authority_mkdir (struct android_vnode *, mode_t);
+static int android_authority_chmod (struct android_vnode *, mode_t, int);
 static struct android_vdir *android_authority_opendir (struct android_vnode *);
 
 /* Vector of VFS operations associated with the content VFS node.  */
@@ -2839,6 +2878,7 @@ static struct android_vops authority_vfs_ops =
     android_authority_stat,
     android_authority_access,
     android_authority_mkdir,
+    android_authority_chmod,
     android_authority_opendir,
   };
 
@@ -3118,6 +3158,14 @@ android_authority_mkdir (struct android_vnode *vnode, 
mode_t mode)
   return -1;
 }
 
+static int
+android_authority_chmod (struct android_vnode *vnode, mode_t mode,
+                        int flags)
+{
+  errno = EACCES;
+  return -1;
+}
+
 static struct android_vdir *
 android_authority_opendir (struct android_vnode *vnode)
 {
@@ -3223,6 +3271,7 @@ static int android_saf_root_rename (struct android_vnode 
*,
 static int android_saf_root_stat (struct android_vnode *, struct stat *);
 static int android_saf_root_access (struct android_vnode *, int);
 static int android_saf_root_mkdir (struct android_vnode *, mode_t);
+static int android_saf_root_chmod (struct android_vnode *, mode_t, int);
 static struct android_vdir *android_saf_root_opendir (struct android_vnode *);
 
 /* Vector of VFS operations associated with the SAF root VFS node.  */
@@ -3239,6 +3288,7 @@ static struct android_vops saf_root_vfs_ops =
     android_saf_root_stat,
     android_saf_root_access,
     android_saf_root_mkdir,
+    android_saf_root_chmod,
     android_saf_root_opendir,
   };
 
@@ -3520,6 +3570,14 @@ android_saf_root_mkdir (struct android_vnode *vnode, 
mode_t mode)
   return -1;
 }
 
+static int
+android_saf_root_chmod (struct android_vnode *vnode, mode_t mode,
+                       int flags)
+{
+  errno = EACCES;
+  return -1;
+}
+
 static struct dirent *
 android_saf_root_readdir (struct android_vdir *vdir)
 {
@@ -4347,6 +4405,7 @@ static int android_saf_tree_rename (struct android_vnode 
*,
 static int android_saf_tree_stat (struct android_vnode *, struct stat *);
 static int android_saf_tree_access (struct android_vnode *, int);
 static int android_saf_tree_mkdir (struct android_vnode *, mode_t);
+static int android_saf_tree_chmod (struct android_vnode *, mode_t, int);
 static struct android_vdir *android_saf_tree_opendir (struct android_vnode *);
 
 /* Vector of VFS operations associated with SAF tree VFS nodes.  */
@@ -4363,6 +4422,7 @@ static struct android_vops saf_tree_vfs_ops =
     android_saf_tree_stat,
     android_saf_tree_access,
     android_saf_tree_mkdir,
+    android_saf_tree_chmod,
     android_saf_tree_opendir,
   };
 
@@ -5100,6 +5160,24 @@ android_saf_tree_mkdir (struct android_vnode *vnode, 
mode_t mode)
   return -1;
 }
 
+static int
+android_saf_tree_chmod (struct android_vnode *vnode, mode_t mode,
+                       int flags)
+{
+  /* Return EACCESS should MODE contain unusual bits besides S_IFDIR |
+     S_IRUSR | S_IXUSR.  */
+
+  if (mode & ~(S_IFDIR | S_IRUSR | S_IXUSR))
+    {
+      errno = EACCES;
+      return -1;
+    }
+
+  /* Otherwise, no further action is necessary, as SAF nodes already
+     pretend to be S_IFDIR | S_IRUSR | S_IXUSR.  */
+  return 0;
+}
+
 /* Open a database Cursor containing each directory entry within the
    supplied SAF tree vnode VP.
 
@@ -5523,6 +5601,7 @@ static struct android_vops saf_file_vfs_ops =
     android_saf_tree_stat,
     android_saf_tree_access,
     android_saf_tree_mkdir,
+    android_saf_tree_chmod,
     android_saf_file_opendir,
   };
 
@@ -5761,6 +5840,7 @@ static int android_saf_new_rename (struct android_vnode *,
 static int android_saf_new_stat (struct android_vnode *, struct stat *);
 static int android_saf_new_access (struct android_vnode *, int);
 static int android_saf_new_mkdir (struct android_vnode *, mode_t);
+static int android_saf_new_chmod (struct android_vnode *, mode_t, int);
 static struct android_vdir *android_saf_new_opendir (struct android_vnode *);
 
 /* Vector of VFS operations associated with SAF new VFS nodes.  */
@@ -5777,6 +5857,7 @@ static struct android_vops saf_new_vfs_ops =
     android_saf_new_stat,
     android_saf_new_access,
     android_saf_new_mkdir,
+    android_saf_new_chmod,
     android_saf_new_opendir,
   };
 
@@ -6038,6 +6119,14 @@ android_saf_new_mkdir (struct android_vnode *vnode, 
mode_t mode)
   return 0;
 }
 
+static int
+android_saf_new_chmod (struct android_vnode *vnode, mode_t mode,
+                      int flags)
+{
+  errno = ENOENT;
+  return -1;
+}
+
 static struct android_vdir *
 android_saf_new_opendir (struct android_vnode *vnode)
 {
@@ -6125,6 +6214,7 @@ static struct android_vops root_vfs_ops =
     android_unix_stat,
     android_unix_access,
     android_unix_mkdir,
+    android_unix_chmod,
     android_unix_opendir,
   };
 
@@ -6810,6 +6900,42 @@ android_faccessat (int dirfd, const char *restrict 
pathname,
   return rc;
 }
 
+/* Like `android_fstatat', but set file modes instead of
+   checking file status and respect FLAGS.  */
+
+int
+android_fchmodat (int dirfd, const char *pathname, mode_t mode,
+                 int flags)
+{
+  char buffer[PATH_MAX + 1];
+  struct android_vnode *vp;
+  int rc;
+
+  if (dirfd == AT_FDCWD || pathname[0] == '/')
+    goto vfs;
+
+  /* Now establish whether DIRFD is a file descriptor corresponding to
+     an open VFS directory stream.  */
+
+  if (!android_fstatat_1 (dirfd, pathname, buffer, PATH_MAX + 1))
+    {
+      pathname = buffer;
+      goto vfs;
+    }
+
+  /* Fall back to fchmodat.  */
+  return fchmodat (dirfd, pathname, mode, flags);
+
+ vfs:
+  vp = android_name_file (pathname);
+  if (!vp)
+    return -1;
+
+  rc = (*vp->ops->chmod) (vp, mode, flags);
+  (*vp->ops->close) (vp);
+  return rc;
+}
+
 /* Like `fdopen', but if FD is a parcel file descriptor, ``detach'' it
    from the original.
 
diff --git a/src/fileio.c b/src/fileio.c
index 1ccb871ce49..1a7a7152844 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -3665,17 +3665,9 @@ command from GNU Coreutils.  */)
     return call4 (handler, Qset_file_modes, absname, mode, flag);
 
   encoded = ENCODE_FILE (absname);
-
-  /* Silently ignore attempts to change the access modes of files
-     within /contents on Android, preventing errors within backup file
-     creation.  */
-
-  if (check_vfs_filename (encoded, NULL))
-    return Qnil;
-
   char *fname = SSDATA (encoded);
   mode_t imode = XFIXNUM (mode) & 07777;
-  if (fchmodat (AT_FDCWD, fname, imode, nofollow) != 0)
+  if (emacs_fchmodat (AT_FDCWD, fname, imode, nofollow) != 0)
     report_file_error ("Doing chmod", absname);
 
   return Qnil;
diff --git a/src/lisp.h b/src/lisp.h
index 5802984a5e7..447912581d7 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -5095,6 +5095,7 @@ extern int emacs_mkdir (const char *, mode_t);
 extern int emacs_renameat_noreplace (int, const char *, int,
                                     const char *);
 extern int emacs_rename (const char *, const char *);
+extern int emacs_fchmodat (int, const char *, mode_t, int);
 extern ptrdiff_t emacs_read (int, void *, ptrdiff_t);
 extern ptrdiff_t emacs_read_quit (int, void *, ptrdiff_t);
 extern ptrdiff_t emacs_write (int, void const *, ptrdiff_t);
diff --git a/src/sysdep.c b/src/sysdep.c
index 0a1905c9196..a995bc66741 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -2719,6 +2719,16 @@ emacs_rename (const char *src, const char *dst)
 #endif /* !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY) */
 }
 
+int
+emacs_fchmodat (int fd, const char *path, mode_t mode, int flags)
+{
+#if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
+  return fchmodat (fd, path, mode, flags);
+#else /* !defined HAVE_ANDROID || defined ANDROID_STUBIFY */
+  return android_fchmodat (fd, path, mode, flags);
+#endif /* !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY) */
+}
+
 /* Maximum number of bytes to read or write in a single system call.
    This works around a serious bug in Linux kernels before 2.6.16; see
    <https://bugzilla.redhat.com/show_bug.cgi?format=multiple&id=612839>.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]