aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2023-08-19 13:25:42 +0800
committerPo Lu2023-08-19 13:25:42 +0800
commit2effd18c97bf542e43203c95dd88114159162dd5 (patch)
treee8122ac2aab7a601d22024582fd90f1eb6bc5be4 /src
parentec8f330df6b512242d0c2d18c8d1e9b112916160 (diff)
downloademacs-2effd18c97bf542e43203c95dd88114159162dd5.tar.gz
emacs-2effd18c97bf542e43203c95dd88114159162dd5.zip
Make some file I/O operations more robust on Android
* src/android.h (android_readlinkat): New prototype. * src/androidvfs.c (struct android_vops): New function pointer `readlink'. (unix_vfs_ops, android_unix_readlink, afs_vfs_ops) (android_afs_readlink, content_vfs_ops, android_content_mkdir) (android_content_chmod, authority_vfs_ops) (android_authority_readlink, saf_root_vfs_ops) (android_saf_root_readlink, saf_tree_vfs_ops) (android_saf_tree_readlink, saf_file_vfs_ops, saf_new_vfs_ops) (android_saf_new_readlink, root_vfs_ops): Implement new `readlink' vops for each vnode type. (android_readlinkat): New function. * src/fileio.c (Fcopy_file): Be more flexible about SELinux errors under Android. (emacs_readlinkat): Use `android_readlink' when built as libemacs.so.
Diffstat (limited to 'src')
-rw-r--r--src/android.h2
-rw-r--r--src/androidvfs.c141
-rw-r--r--src/fileio.c34
3 files changed, 170 insertions, 7 deletions
diff --git a/src/android.h b/src/android.h
index a052d3a3b21..e865d7da665 100644
--- a/src/android.h
+++ b/src/android.h
@@ -75,6 +75,8 @@ extern int android_renameat_noreplace (int, const char *,
75 int, const char *); 75 int, const char *);
76extern int android_rename (const char *, const char *); 76extern int android_rename (const char *, const char *);
77extern int android_fchmodat (int, const char *, mode_t, int); 77extern int android_fchmodat (int, const char *, mode_t, int);
78extern ssize_t android_readlinkat (int, const char *restrict, char *restrict,
79 size_t);
78 80
79 81
80 82
diff --git a/src/androidvfs.c b/src/androidvfs.c
index ec33687f34c..d6b832d6caf 100644
--- a/src/androidvfs.c
+++ b/src/androidvfs.c
@@ -214,6 +214,10 @@ struct android_vops
214 AT_SYMLINK_NOFOLLOW. */ 214 AT_SYMLINK_NOFOLLOW. */
215 int (*chmod) (struct android_vnode *, mode_t, int); 215 int (*chmod) (struct android_vnode *, mode_t, int);
216 216
217 /* Return the target of VNODE if it is a symbolic link, or -1.
218 Value and errno are the same as with `readlink'. */
219 ssize_t (*readlink) (struct android_vnode *, char *, size_t);
220
217 /* Open the specified VNODE as a directory. 221 /* Open the specified VNODE as a directory.
218 Value is a ``directory handle'', or NULL upon failure. */ 222 Value is a ``directory handle'', or NULL upon failure. */
219 struct android_vdir *(*opendir) (struct android_vnode *); 223 struct android_vdir *(*opendir) (struct android_vnode *);
@@ -625,6 +629,8 @@ static int android_unix_stat (struct android_vnode *, struct stat *);
625static int android_unix_access (struct android_vnode *, int); 629static int android_unix_access (struct android_vnode *, int);
626static int android_unix_mkdir (struct android_vnode *, mode_t); 630static int android_unix_mkdir (struct android_vnode *, mode_t);
627static int android_unix_chmod (struct android_vnode *, mode_t, int); 631static int android_unix_chmod (struct android_vnode *, mode_t, int);
632static ssize_t android_unix_readlink (struct android_vnode *, char *,
633 size_t);
628static struct android_vdir *android_unix_opendir (struct android_vnode *); 634static struct android_vdir *android_unix_opendir (struct android_vnode *);
629 635
630/* Vector of VFS operations associated with Unix filesystem VFS 636/* Vector of VFS operations associated with Unix filesystem VFS
@@ -643,6 +649,7 @@ static struct android_vops unix_vfs_ops =
643 android_unix_access, 649 android_unix_access,
644 android_unix_mkdir, 650 android_unix_mkdir,
645 android_unix_chmod, 651 android_unix_chmod,
652 android_unix_readlink,
646 android_unix_opendir, 653 android_unix_opendir,
647 }; 654 };
648 655
@@ -898,6 +905,16 @@ android_unix_chmod (struct android_vnode *vnode, mode_t mode,
898 return fchmodat (AT_FDCWD, vp->name, mode, flags); 905 return fchmodat (AT_FDCWD, vp->name, mode, flags);
899} 906}
900 907
908static ssize_t
909android_unix_readlink (struct android_vnode *vnode, char *buffer,
910 size_t size)
911{
912 struct android_unix_vnode *vp;
913
914 vp = (struct android_unix_vnode *) vnode;
915 return readlink (vp->name, buffer, size);
916}
917
901static struct dirent * 918static struct dirent *
902android_unix_readdir (struct android_vdir *vdir) 919android_unix_readdir (struct android_vdir *vdir)
903{ 920{
@@ -1606,6 +1623,8 @@ static int android_afs_stat (struct android_vnode *, struct stat *);
1606static int android_afs_access (struct android_vnode *, int); 1623static int android_afs_access (struct android_vnode *, int);
1607static int android_afs_mkdir (struct android_vnode *, mode_t); 1624static int android_afs_mkdir (struct android_vnode *, mode_t);
1608static int android_afs_chmod (struct android_vnode *, mode_t, int); 1625static int android_afs_chmod (struct android_vnode *, mode_t, int);
1626static ssize_t android_afs_readlink (struct android_vnode *, char *,
1627 size_t);
1609static struct android_vdir *android_afs_opendir (struct android_vnode *); 1628static struct android_vdir *android_afs_opendir (struct android_vnode *);
1610 1629
1611/* Vector of VFS operations associated with asset VFS nodes. */ 1630/* Vector of VFS operations associated with asset VFS nodes. */
@@ -1623,6 +1642,7 @@ static struct android_vops afs_vfs_ops =
1623 android_afs_access, 1642 android_afs_access,
1624 android_afs_mkdir, 1643 android_afs_mkdir,
1625 android_afs_chmod, 1644 android_afs_chmod,
1645 android_afs_readlink,
1626 android_afs_opendir, 1646 android_afs_opendir,
1627 }; 1647 };
1628 1648
@@ -2139,6 +2159,28 @@ android_afs_chmod (struct android_vnode *vnode, mode_t mode,
2139 return -1; 2159 return -1;
2140} 2160}
2141 2161
2162static ssize_t
2163android_afs_readlink (struct android_vnode *vnode, char *buffer,
2164 size_t size)
2165{
2166 struct android_afs_vnode *vp;
2167 const char *dir;
2168
2169 vp = (struct android_afs_vnode *) vnode;
2170 dir = android_scan_directory_tree (vp->name, NULL);
2171
2172 /* As there are no symlinks in /assets, just return -1 with errno
2173 set to a reasonable value contingent upon whether VP->name
2174 actually exists. */
2175
2176 if (dir)
2177 errno = EINVAL;
2178 else
2179 errno = ENOENT;
2180
2181 return -1;
2182}
2183
2142static struct dirent * 2184static struct dirent *
2143android_afs_readdir (struct android_vdir *vdir) 2185android_afs_readdir (struct android_vdir *vdir)
2144{ 2186{
@@ -2379,6 +2421,8 @@ static int android_content_stat (struct android_vnode *, struct stat *);
2379static int android_content_access (struct android_vnode *, int); 2421static int android_content_access (struct android_vnode *, int);
2380static int android_content_mkdir (struct android_vnode *, mode_t); 2422static int android_content_mkdir (struct android_vnode *, mode_t);
2381static int android_content_chmod (struct android_vnode *, mode_t, int); 2423static int android_content_chmod (struct android_vnode *, mode_t, int);
2424static ssize_t android_content_readlink (struct android_vnode *, char *,
2425 size_t);
2382static struct android_vdir *android_content_opendir (struct android_vnode *); 2426static struct android_vdir *android_content_opendir (struct android_vnode *);
2383 2427
2384/* Vector of VFS operations associated with the content VFS node. */ 2428/* Vector of VFS operations associated with the content VFS node. */
@@ -2396,6 +2440,7 @@ static struct android_vops content_vfs_ops =
2396 android_content_access, 2440 android_content_access,
2397 android_content_mkdir, 2441 android_content_mkdir,
2398 android_content_chmod, 2442 android_content_chmod,
2443 android_content_readlink,
2399 android_content_opendir, 2444 android_content_opendir,
2400 }; 2445 };
2401 2446
@@ -2600,7 +2645,7 @@ static int
2600android_content_mkdir (struct android_vnode *vnode, mode_t mode) 2645android_content_mkdir (struct android_vnode *vnode, mode_t mode)
2601{ 2646{
2602 errno = EEXIST; 2647 errno = EEXIST;
2603 return 0; 2648 return -1;
2604} 2649}
2605 2650
2606static int 2651static int
@@ -2608,7 +2653,15 @@ android_content_chmod (struct android_vnode *vnode, mode_t mode,
2608 int flags) 2653 int flags)
2609{ 2654{
2610 errno = EACCES; 2655 errno = EACCES;
2611 return 0; 2656 return -1;
2657}
2658
2659static ssize_t
2660android_content_readlink (struct android_vnode *vnode, char *buffer,
2661 size_t size)
2662{
2663 errno = EINVAL;
2664 return -1;
2612} 2665}
2613 2666
2614static struct dirent * 2667static struct dirent *
@@ -2865,6 +2918,8 @@ static int android_authority_stat (struct android_vnode *, struct stat *);
2865static int android_authority_access (struct android_vnode *, int); 2918static int android_authority_access (struct android_vnode *, int);
2866static int android_authority_mkdir (struct android_vnode *, mode_t); 2919static int android_authority_mkdir (struct android_vnode *, mode_t);
2867static int android_authority_chmod (struct android_vnode *, mode_t, int); 2920static int android_authority_chmod (struct android_vnode *, mode_t, int);
2921static ssize_t android_authority_readlink (struct android_vnode *, char *,
2922 size_t);
2868static struct android_vdir *android_authority_opendir (struct android_vnode *); 2923static struct android_vdir *android_authority_opendir (struct android_vnode *);
2869 2924
2870/* Vector of VFS operations associated with the content VFS node. */ 2925/* Vector of VFS operations associated with the content VFS node. */
@@ -2882,6 +2937,7 @@ static struct android_vops authority_vfs_ops =
2882 android_authority_access, 2937 android_authority_access,
2883 android_authority_mkdir, 2938 android_authority_mkdir,
2884 android_authority_chmod, 2939 android_authority_chmod,
2940 android_authority_readlink,
2885 android_authority_opendir, 2941 android_authority_opendir,
2886 }; 2942 };
2887 2943
@@ -3176,6 +3232,14 @@ android_authority_chmod (struct android_vnode *vnode, mode_t mode,
3176 return -1; 3232 return -1;
3177} 3233}
3178 3234
3235static ssize_t
3236android_authority_readlink (struct android_vnode *vnode, char *buffer,
3237 size_t size)
3238{
3239 errno = EINVAL;
3240 return -1;
3241}
3242
3179static struct android_vdir * 3243static struct android_vdir *
3180android_authority_opendir (struct android_vnode *vnode) 3244android_authority_opendir (struct android_vnode *vnode)
3181{ 3245{
@@ -3282,6 +3346,8 @@ static int android_saf_root_stat (struct android_vnode *, struct stat *);
3282static int android_saf_root_access (struct android_vnode *, int); 3346static int android_saf_root_access (struct android_vnode *, int);
3283static int android_saf_root_mkdir (struct android_vnode *, mode_t); 3347static int android_saf_root_mkdir (struct android_vnode *, mode_t);
3284static int android_saf_root_chmod (struct android_vnode *, mode_t, int); 3348static int android_saf_root_chmod (struct android_vnode *, mode_t, int);
3349static ssize_t android_saf_root_readlink (struct android_vnode *, char *,
3350 size_t);
3285static struct android_vdir *android_saf_root_opendir (struct android_vnode *); 3351static struct android_vdir *android_saf_root_opendir (struct android_vnode *);
3286 3352
3287/* Vector of VFS operations associated with the SAF root VFS node. */ 3353/* Vector of VFS operations associated with the SAF root VFS node. */
@@ -3299,6 +3365,7 @@ static struct android_vops saf_root_vfs_ops =
3299 android_saf_root_access, 3365 android_saf_root_access,
3300 android_saf_root_mkdir, 3366 android_saf_root_mkdir,
3301 android_saf_root_chmod, 3367 android_saf_root_chmod,
3368 android_saf_root_readlink,
3302 android_saf_root_opendir, 3369 android_saf_root_opendir,
3303 }; 3370 };
3304 3371
@@ -3585,6 +3652,14 @@ android_saf_root_chmod (struct android_vnode *vnode, mode_t mode,
3585 return -1; 3652 return -1;
3586} 3653}
3587 3654
3655static ssize_t
3656android_saf_root_readlink (struct android_vnode *vnode, char *buffer,
3657 size_t size)
3658{
3659 errno = EINVAL;
3660 return -1;
3661}
3662
3588static struct dirent * 3663static struct dirent *
3589android_saf_root_readdir (struct android_vdir *vdir) 3664android_saf_root_readdir (struct android_vdir *vdir)
3590{ 3665{
@@ -4426,6 +4501,8 @@ static int android_saf_tree_stat (struct android_vnode *, struct stat *);
4426static int android_saf_tree_access (struct android_vnode *, int); 4501static int android_saf_tree_access (struct android_vnode *, int);
4427static int android_saf_tree_mkdir (struct android_vnode *, mode_t); 4502static int android_saf_tree_mkdir (struct android_vnode *, mode_t);
4428static int android_saf_tree_chmod (struct android_vnode *, mode_t, int); 4503static int android_saf_tree_chmod (struct android_vnode *, mode_t, int);
4504static ssize_t android_saf_tree_readlink (struct android_vnode *, char *,
4505 size_t);
4429static struct android_vdir *android_saf_tree_opendir (struct android_vnode *); 4506static struct android_vdir *android_saf_tree_opendir (struct android_vnode *);
4430 4507
4431/* Vector of VFS operations associated with SAF tree VFS nodes. */ 4508/* Vector of VFS operations associated with SAF tree VFS nodes. */
@@ -4443,6 +4520,7 @@ static struct android_vops saf_tree_vfs_ops =
4443 android_saf_tree_access, 4520 android_saf_tree_access,
4444 android_saf_tree_mkdir, 4521 android_saf_tree_mkdir,
4445 android_saf_tree_chmod, 4522 android_saf_tree_chmod,
4523 android_saf_tree_readlink,
4446 android_saf_tree_opendir, 4524 android_saf_tree_opendir,
4447 }; 4525 };
4448 4526
@@ -5138,6 +5216,16 @@ android_saf_tree_chmod (struct android_vnode *vnode, mode_t mode,
5138 return 0; 5216 return 0;
5139} 5217}
5140 5218
5219static ssize_t
5220android_saf_tree_readlink (struct android_vnode *vnode, char *buffer,
5221 size_t size)
5222{
5223 /* Return EINVAL. Symlinks aren't exposed to clients by the
5224 SAF. */
5225 errno = EINVAL;
5226 return -1;
5227}
5228
5141/* Open a database Cursor containing each directory entry within the 5229/* Open a database Cursor containing each directory entry within the
5142 supplied SAF tree vnode VP. 5230 supplied SAF tree vnode VP.
5143 5231
@@ -5562,6 +5650,7 @@ static struct android_vops saf_file_vfs_ops =
5562 android_saf_tree_access, 5650 android_saf_tree_access,
5563 android_saf_tree_mkdir, 5651 android_saf_tree_mkdir,
5564 android_saf_tree_chmod, 5652 android_saf_tree_chmod,
5653 android_saf_tree_readlink,
5565 android_saf_file_opendir, 5654 android_saf_file_opendir,
5566 }; 5655 };
5567 5656
@@ -5842,6 +5931,8 @@ static int android_saf_new_stat (struct android_vnode *, struct stat *);
5842static int android_saf_new_access (struct android_vnode *, int); 5931static int android_saf_new_access (struct android_vnode *, int);
5843static int android_saf_new_mkdir (struct android_vnode *, mode_t); 5932static int android_saf_new_mkdir (struct android_vnode *, mode_t);
5844static int android_saf_new_chmod (struct android_vnode *, mode_t, int); 5933static int android_saf_new_chmod (struct android_vnode *, mode_t, int);
5934static ssize_t android_saf_new_readlink (struct android_vnode *, char *,
5935 size_t);
5845static struct android_vdir *android_saf_new_opendir (struct android_vnode *); 5936static struct android_vdir *android_saf_new_opendir (struct android_vnode *);
5846 5937
5847/* Vector of VFS operations associated with SAF new VFS nodes. */ 5938/* Vector of VFS operations associated with SAF new VFS nodes. */
@@ -5859,6 +5950,7 @@ static struct android_vops saf_new_vfs_ops =
5859 android_saf_new_access, 5950 android_saf_new_access,
5860 android_saf_new_mkdir, 5951 android_saf_new_mkdir,
5861 android_saf_new_chmod, 5952 android_saf_new_chmod,
5953 android_saf_new_readlink,
5862 android_saf_new_opendir, 5954 android_saf_new_opendir,
5863 }; 5955 };
5864 5956
@@ -6128,6 +6220,14 @@ android_saf_new_chmod (struct android_vnode *vnode, mode_t mode,
6128 return -1; 6220 return -1;
6129} 6221}
6130 6222
6223static ssize_t
6224android_saf_new_readlink (struct android_vnode *vnode, char *buffer,
6225 size_t size)
6226{
6227 errno = ENOENT;
6228 return -1;
6229}
6230
6131static struct android_vdir * 6231static struct android_vdir *
6132android_saf_new_opendir (struct android_vnode *vnode) 6232android_saf_new_opendir (struct android_vnode *vnode)
6133{ 6233{
@@ -6229,6 +6329,7 @@ static struct android_vops root_vfs_ops =
6229 android_unix_access, 6329 android_unix_access,
6230 android_unix_mkdir, 6330 android_unix_mkdir,
6231 android_unix_chmod, 6331 android_unix_chmod,
6332 android_unix_readlink,
6232 android_unix_opendir, 6333 android_unix_opendir,
6233 }; 6334 };
6234 6335
@@ -6962,6 +7063,42 @@ android_fchmodat (int dirfd, const char *pathname, mode_t mode,
6962 return rc; 7063 return rc;
6963} 7064}
6964 7065
7066/* Like `android_fstatat', but return the target of any symbolic link
7067 at PATHNAME instead of checking file status. */
7068
7069ssize_t
7070android_readlinkat (int dirfd, const char *restrict pathname,
7071 char *restrict buf, size_t bufsiz)
7072{
7073 char buffer[PATH_MAX + 1];
7074 struct android_vnode *vp;
7075 ssize_t rc;
7076
7077 if (dirfd == AT_FDCWD || pathname[0] == '/')
7078 goto vfs;
7079
7080 /* Now establish whether DIRFD is a file descriptor corresponding to
7081 an open VFS directory stream. */
7082
7083 if (!android_fstatat_1 (dirfd, pathname, buffer, PATH_MAX + 1))
7084 {
7085 pathname = buffer;
7086 goto vfs;
7087 }
7088
7089 /* Fall back to readlinkat. */
7090 return readlinkat (dirfd, pathname, buf, bufsiz);
7091
7092 vfs:
7093 vp = android_name_file (pathname);
7094 if (!vp)
7095 return -1;
7096
7097 rc = (*vp->ops->readlink) (vp, buf, bufsiz);
7098 (*vp->ops->close) (vp);
7099 return rc;
7100}
7101
6965/* Like `fdopen', but if FD is a parcel file descriptor, ``detach'' it 7102/* Like `fdopen', but if FD is a parcel file descriptor, ``detach'' it
6966 from the original. 7103 from the original.
6967 7104
diff --git a/src/fileio.c b/src/fileio.c
index 869e1ea7e31..9294ea3e7d6 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -2331,6 +2331,9 @@ permissions. */)
2331 { 2331 {
2332#if HAVE_LIBSELINUX 2332#if HAVE_LIBSELINUX
2333 if (selinux_enabled_p (SSDATA (encoded_file)) 2333 if (selinux_enabled_p (SSDATA (encoded_file))
2334 /* Eschew copying SELinux contexts if they're inapplicable
2335 to the destination file. */
2336 && selinux_enabled_p (SSDATA (encoded_newname))
2334 && emacs_fd_to_int (ifd) != -1) 2337 && emacs_fd_to_int (ifd) != -1)
2335 { 2338 {
2336 conlength = fgetfilecon (emacs_fd_to_int (ifd), 2339 conlength = fgetfilecon (emacs_fd_to_int (ifd),
@@ -2494,7 +2497,14 @@ permissions. */)
2494 /* Set the modified context back to the file. */ 2497 /* Set the modified context back to the file. */
2495 bool fail = fsetfilecon (ofd, con) != 0; 2498 bool fail = fsetfilecon (ofd, con) != 0;
2496 /* See https://debbugs.gnu.org/11245 for ENOTSUP. */ 2499 /* See https://debbugs.gnu.org/11245 for ENOTSUP. */
2497 if (fail && errno != ENOTSUP) 2500 if (fail
2501#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
2502 /* Treat SELinux errors copying files leniently on Android,
2503 since the system usually forbids user programs from
2504 changing file contexts. */
2505 && errno != EACCES
2506#endif /* defined HAVE_ANDROID && !defined ANDROID_STUBIFY */
2507 && errno != ENOTSUP)
2498 report_file_error ("Doing fsetfilecon", newname); 2508 report_file_error ("Doing fsetfilecon", newname);
2499 2509
2500 freecon (con); 2510 freecon (con);
@@ -3090,15 +3100,29 @@ If there is no error, returns nil. */)
3090 3100
3091/* Relative to directory FD, return the symbolic link value of FILENAME. 3101/* Relative to directory FD, return the symbolic link value of FILENAME.
3092 On failure, return nil (setting errno). */ 3102 On failure, return nil (setting errno). */
3103
3093static Lisp_Object 3104static Lisp_Object
3094emacs_readlinkat (int fd, char const *filename) 3105emacs_readlinkat (int fd, char const *filename)
3095{ 3106{
3096 static struct allocator const emacs_norealloc_allocator = 3107 static struct allocator const emacs_norealloc_allocator = {
3097 { xmalloc, NULL, xfree, memory_full }; 3108 xmalloc,
3109 NULL,
3110 xfree,
3111 memory_full,
3112 };
3113
3098 Lisp_Object val; 3114 Lisp_Object val;
3099 char readlink_buf[1024]; 3115 char readlink_buf[1024];
3100 char *buf = careadlinkat (fd, filename, readlink_buf, sizeof readlink_buf, 3116 char *buf;
3101 &emacs_norealloc_allocator, readlinkat); 3117
3118 buf = careadlinkat (fd, filename, readlink_buf, sizeof readlink_buf,
3119 &emacs_norealloc_allocator,
3120#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
3121 android_readlinkat
3122#else /* !HAVE_ANDROID || ANDROID_STUBIFY */
3123 readlinkat
3124#endif /* HAVE_ANDROID && !ANDROID_STUBIFY */
3125 );
3102 if (!buf) 3126 if (!buf)
3103 return Qnil; 3127 return Qnil;
3104 3128