diff options
| author | Po Lu | 2023-08-19 13:25:42 +0800 |
|---|---|---|
| committer | Po Lu | 2023-08-19 13:25:42 +0800 |
| commit | 2effd18c97bf542e43203c95dd88114159162dd5 (patch) | |
| tree | e8122ac2aab7a601d22024582fd90f1eb6bc5be4 /src | |
| parent | ec8f330df6b512242d0c2d18c8d1e9b112916160 (diff) | |
| download | emacs-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.h | 2 | ||||
| -rw-r--r-- | src/androidvfs.c | 141 | ||||
| -rw-r--r-- | src/fileio.c | 34 |
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 *); |
| 76 | extern int android_rename (const char *, const char *); | 76 | extern int android_rename (const char *, const char *); |
| 77 | extern int android_fchmodat (int, const char *, mode_t, int); | 77 | extern int android_fchmodat (int, const char *, mode_t, int); |
| 78 | extern 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 *); | |||
| 625 | static int android_unix_access (struct android_vnode *, int); | 629 | static int android_unix_access (struct android_vnode *, int); |
| 626 | static int android_unix_mkdir (struct android_vnode *, mode_t); | 630 | static int android_unix_mkdir (struct android_vnode *, mode_t); |
| 627 | static int android_unix_chmod (struct android_vnode *, mode_t, int); | 631 | static int android_unix_chmod (struct android_vnode *, mode_t, int); |
| 632 | static ssize_t android_unix_readlink (struct android_vnode *, char *, | ||
| 633 | size_t); | ||
| 628 | static struct android_vdir *android_unix_opendir (struct android_vnode *); | 634 | static 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 | ||
| 908 | static ssize_t | ||
| 909 | android_unix_readlink (struct android_vnode *vnode, char *buffer, | ||
| 910 | size_t size) | ||
| 911 | { | ||
| 912 | struct android_unix_vnode *vp; | ||
| 913 | |||
| 914 | vp = (struct android_unix_vnode *) vnode; | ||
| 915 | return readlink (vp->name, buffer, size); | ||
| 916 | } | ||
| 917 | |||
| 901 | static struct dirent * | 918 | static struct dirent * |
| 902 | android_unix_readdir (struct android_vdir *vdir) | 919 | android_unix_readdir (struct android_vdir *vdir) |
| 903 | { | 920 | { |
| @@ -1606,6 +1623,8 @@ static int android_afs_stat (struct android_vnode *, struct stat *); | |||
| 1606 | static int android_afs_access (struct android_vnode *, int); | 1623 | static int android_afs_access (struct android_vnode *, int); |
| 1607 | static int android_afs_mkdir (struct android_vnode *, mode_t); | 1624 | static int android_afs_mkdir (struct android_vnode *, mode_t); |
| 1608 | static int android_afs_chmod (struct android_vnode *, mode_t, int); | 1625 | static int android_afs_chmod (struct android_vnode *, mode_t, int); |
| 1626 | static ssize_t android_afs_readlink (struct android_vnode *, char *, | ||
| 1627 | size_t); | ||
| 1609 | static struct android_vdir *android_afs_opendir (struct android_vnode *); | 1628 | static 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 | ||
| 2162 | static ssize_t | ||
| 2163 | android_afs_readlink (struct android_vnode *vnode, char *buffer, | ||
| 2164 | size_t size) | ||
| 2165 | { | ||
| 2166 | struct android_afs_vnode *vp; | ||
| 2167 | const char *dir; | ||
| 2168 | |||
| 2169 | vp = (struct android_afs_vnode *) vnode; | ||
| 2170 | dir = android_scan_directory_tree (vp->name, NULL); | ||
| 2171 | |||
| 2172 | /* As there are no symlinks in /assets, just return -1 with errno | ||
| 2173 | set to a reasonable value contingent upon whether VP->name | ||
| 2174 | actually exists. */ | ||
| 2175 | |||
| 2176 | if (dir) | ||
| 2177 | errno = EINVAL; | ||
| 2178 | else | ||
| 2179 | errno = ENOENT; | ||
| 2180 | |||
| 2181 | return -1; | ||
| 2182 | } | ||
| 2183 | |||
| 2142 | static struct dirent * | 2184 | static struct dirent * |
| 2143 | android_afs_readdir (struct android_vdir *vdir) | 2185 | android_afs_readdir (struct android_vdir *vdir) |
| 2144 | { | 2186 | { |
| @@ -2379,6 +2421,8 @@ static int android_content_stat (struct android_vnode *, struct stat *); | |||
| 2379 | static int android_content_access (struct android_vnode *, int); | 2421 | static int android_content_access (struct android_vnode *, int); |
| 2380 | static int android_content_mkdir (struct android_vnode *, mode_t); | 2422 | static int android_content_mkdir (struct android_vnode *, mode_t); |
| 2381 | static int android_content_chmod (struct android_vnode *, mode_t, int); | 2423 | static int android_content_chmod (struct android_vnode *, mode_t, int); |
| 2424 | static ssize_t android_content_readlink (struct android_vnode *, char *, | ||
| 2425 | size_t); | ||
| 2382 | static struct android_vdir *android_content_opendir (struct android_vnode *); | 2426 | static 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 | |||
| 2600 | android_content_mkdir (struct android_vnode *vnode, mode_t mode) | 2645 | android_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 | ||
| 2606 | static int | 2651 | static 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 | |||
| 2659 | static ssize_t | ||
| 2660 | android_content_readlink (struct android_vnode *vnode, char *buffer, | ||
| 2661 | size_t size) | ||
| 2662 | { | ||
| 2663 | errno = EINVAL; | ||
| 2664 | return -1; | ||
| 2612 | } | 2665 | } |
| 2613 | 2666 | ||
| 2614 | static struct dirent * | 2667 | static struct dirent * |
| @@ -2865,6 +2918,8 @@ static int android_authority_stat (struct android_vnode *, struct stat *); | |||
| 2865 | static int android_authority_access (struct android_vnode *, int); | 2918 | static int android_authority_access (struct android_vnode *, int); |
| 2866 | static int android_authority_mkdir (struct android_vnode *, mode_t); | 2919 | static int android_authority_mkdir (struct android_vnode *, mode_t); |
| 2867 | static int android_authority_chmod (struct android_vnode *, mode_t, int); | 2920 | static int android_authority_chmod (struct android_vnode *, mode_t, int); |
| 2921 | static ssize_t android_authority_readlink (struct android_vnode *, char *, | ||
| 2922 | size_t); | ||
| 2868 | static struct android_vdir *android_authority_opendir (struct android_vnode *); | 2923 | static 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 | ||
| 3235 | static ssize_t | ||
| 3236 | android_authority_readlink (struct android_vnode *vnode, char *buffer, | ||
| 3237 | size_t size) | ||
| 3238 | { | ||
| 3239 | errno = EINVAL; | ||
| 3240 | return -1; | ||
| 3241 | } | ||
| 3242 | |||
| 3179 | static struct android_vdir * | 3243 | static struct android_vdir * |
| 3180 | android_authority_opendir (struct android_vnode *vnode) | 3244 | android_authority_opendir (struct android_vnode *vnode) |
| 3181 | { | 3245 | { |
| @@ -3282,6 +3346,8 @@ static int android_saf_root_stat (struct android_vnode *, struct stat *); | |||
| 3282 | static int android_saf_root_access (struct android_vnode *, int); | 3346 | static int android_saf_root_access (struct android_vnode *, int); |
| 3283 | static int android_saf_root_mkdir (struct android_vnode *, mode_t); | 3347 | static int android_saf_root_mkdir (struct android_vnode *, mode_t); |
| 3284 | static int android_saf_root_chmod (struct android_vnode *, mode_t, int); | 3348 | static int android_saf_root_chmod (struct android_vnode *, mode_t, int); |
| 3349 | static ssize_t android_saf_root_readlink (struct android_vnode *, char *, | ||
| 3350 | size_t); | ||
| 3285 | static struct android_vdir *android_saf_root_opendir (struct android_vnode *); | 3351 | static 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 | ||
| 3655 | static ssize_t | ||
| 3656 | android_saf_root_readlink (struct android_vnode *vnode, char *buffer, | ||
| 3657 | size_t size) | ||
| 3658 | { | ||
| 3659 | errno = EINVAL; | ||
| 3660 | return -1; | ||
| 3661 | } | ||
| 3662 | |||
| 3588 | static struct dirent * | 3663 | static struct dirent * |
| 3589 | android_saf_root_readdir (struct android_vdir *vdir) | 3664 | android_saf_root_readdir (struct android_vdir *vdir) |
| 3590 | { | 3665 | { |
| @@ -4426,6 +4501,8 @@ static int android_saf_tree_stat (struct android_vnode *, struct stat *); | |||
| 4426 | static int android_saf_tree_access (struct android_vnode *, int); | 4501 | static int android_saf_tree_access (struct android_vnode *, int); |
| 4427 | static int android_saf_tree_mkdir (struct android_vnode *, mode_t); | 4502 | static int android_saf_tree_mkdir (struct android_vnode *, mode_t); |
| 4428 | static int android_saf_tree_chmod (struct android_vnode *, mode_t, int); | 4503 | static int android_saf_tree_chmod (struct android_vnode *, mode_t, int); |
| 4504 | static ssize_t android_saf_tree_readlink (struct android_vnode *, char *, | ||
| 4505 | size_t); | ||
| 4429 | static struct android_vdir *android_saf_tree_opendir (struct android_vnode *); | 4506 | static 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 | ||
| 5219 | static ssize_t | ||
| 5220 | android_saf_tree_readlink (struct android_vnode *vnode, char *buffer, | ||
| 5221 | size_t size) | ||
| 5222 | { | ||
| 5223 | /* Return EINVAL. Symlinks aren't exposed to clients by the | ||
| 5224 | SAF. */ | ||
| 5225 | errno = EINVAL; | ||
| 5226 | return -1; | ||
| 5227 | } | ||
| 5228 | |||
| 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 *); | |||
| 5842 | static int android_saf_new_access (struct android_vnode *, int); | 5931 | static int android_saf_new_access (struct android_vnode *, int); |
| 5843 | static int android_saf_new_mkdir (struct android_vnode *, mode_t); | 5932 | static int android_saf_new_mkdir (struct android_vnode *, mode_t); |
| 5844 | static int android_saf_new_chmod (struct android_vnode *, mode_t, int); | 5933 | static int android_saf_new_chmod (struct android_vnode *, mode_t, int); |
| 5934 | static ssize_t android_saf_new_readlink (struct android_vnode *, char *, | ||
| 5935 | size_t); | ||
| 5845 | static struct android_vdir *android_saf_new_opendir (struct android_vnode *); | 5936 | static 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 | ||
| 6223 | static ssize_t | ||
| 6224 | android_saf_new_readlink (struct android_vnode *vnode, char *buffer, | ||
| 6225 | size_t size) | ||
| 6226 | { | ||
| 6227 | errno = ENOENT; | ||
| 6228 | return -1; | ||
| 6229 | } | ||
| 6230 | |||
| 6131 | static struct android_vdir * | 6231 | static struct android_vdir * |
| 6132 | android_saf_new_opendir (struct android_vnode *vnode) | 6232 | android_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 | |||
| 7069 | ssize_t | ||
| 7070 | android_readlinkat (int dirfd, const char *restrict pathname, | ||
| 7071 | char *restrict buf, size_t bufsiz) | ||
| 7072 | { | ||
| 7073 | char buffer[PATH_MAX + 1]; | ||
| 7074 | struct android_vnode *vp; | ||
| 7075 | ssize_t rc; | ||
| 7076 | |||
| 7077 | if (dirfd == AT_FDCWD || pathname[0] == '/') | ||
| 7078 | goto vfs; | ||
| 7079 | |||
| 7080 | /* Now establish whether DIRFD is a file descriptor corresponding to | ||
| 7081 | an open VFS directory stream. */ | ||
| 7082 | |||
| 7083 | if (!android_fstatat_1 (dirfd, pathname, buffer, PATH_MAX + 1)) | ||
| 7084 | { | ||
| 7085 | pathname = buffer; | ||
| 7086 | goto vfs; | ||
| 7087 | } | ||
| 7088 | |||
| 7089 | /* Fall back to readlinkat. */ | ||
| 7090 | return readlinkat (dirfd, pathname, buf, bufsiz); | ||
| 7091 | |||
| 7092 | vfs: | ||
| 7093 | vp = android_name_file (pathname); | ||
| 7094 | if (!vp) | ||
| 7095 | return -1; | ||
| 7096 | |||
| 7097 | rc = (*vp->ops->readlink) (vp, buf, bufsiz); | ||
| 7098 | (*vp->ops->close) (vp); | ||
| 7099 | return rc; | ||
| 7100 | } | ||
| 7101 | |||
| 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 | |||
| 3093 | static Lisp_Object | 3104 | static Lisp_Object |
| 3094 | emacs_readlinkat (int fd, char const *filename) | 3105 | emacs_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 | ||