aboutsummaryrefslogtreecommitdiffstats
path: root/src/android.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/android.c')
-rw-r--r--src/android.c168
1 files changed, 164 insertions, 4 deletions
diff --git a/src/android.c b/src/android.c
index 3f6e6f4576b..a51d0518484 100644
--- a/src/android.c
+++ b/src/android.c
@@ -852,6 +852,26 @@ android_scan_directory_tree (char *file, size_t *limit_return)
852 return NULL; 852 return NULL;
853} 853}
854 854
855/* Return whether or not the directory tree entry DIR is a
856 directory.
857
858 DIR should be a value returned by
859 `android_scan_directory_tree'. */
860
861static bool
862android_is_directory (const char *dir)
863{
864 /* If the directory is the directory tree, then it is a
865 directory. */
866 if (dir == directory_tree + 5)
867 return true;
868
869 /* Otherwise, look 5 bytes behind. If it is `/', then it is a
870 directory. */
871 return (dir - 6 >= directory_tree
872 && *(dir - 6) == '/');
873}
874
855 875
856 876
857/* Intercept USER_FULL_NAME and return something that makes sense if 877/* Intercept USER_FULL_NAME and return something that makes sense if
@@ -899,8 +919,15 @@ android_fstat (int fd, struct stat *statb)
899 return fstat (fd, statb); 919 return fstat (fd, statb);
900} 920}
901 921
922static int android_lookup_asset_directory_fd (int,
923 const char *restrict *,
924 const char *restrict);
925
902/* Like fstatat. However, if dirfd is AT_FDCWD and PATHNAME is an 926/* Like fstatat. However, if dirfd is AT_FDCWD and PATHNAME is an
903 asset, find the information for the corresponding asset. */ 927 asset, find the information for the corresponding asset, and if
928 dirfd is an offset into directory_tree as returned by
929 `android_dirfd', find the information within the corresponding
930 directory tree entry. */
904 931
905int 932int
906android_fstatat (int dirfd, const char *restrict pathname, 933android_fstatat (int dirfd, const char *restrict pathname,
@@ -908,11 +935,40 @@ android_fstatat (int dirfd, const char *restrict pathname,
908{ 935{
909 AAsset *asset_desc; 936 AAsset *asset_desc;
910 const char *asset; 937 const char *asset;
938 const char *asset_dir;
939
940 /* Look up whether or not DIRFD belongs to an open struct
941 android_dir. */
942
943 if (dirfd != AT_FDCWD)
944 dirfd
945 = android_lookup_asset_directory_fd (dirfd, &pathname,
946 pathname);
911 947
912 if (dirfd == AT_FDCWD 948 if (dirfd == AT_FDCWD
913 && asset_manager 949 && asset_manager
914 && (asset = android_get_asset_name (pathname))) 950 && (asset = android_get_asset_name (pathname)))
915 { 951 {
952 /* Look up whether or not PATHNAME happens to be a
953 directory. */
954 asset_dir = android_scan_directory_tree ((char *) asset,
955 NULL);
956
957 if (!asset_dir)
958 {
959 errno = ENOENT;
960 return -1;
961 }
962
963 if (android_is_directory (asset_dir))
964 {
965 memset (statbuf, 0, sizeof *statbuf);
966
967 /* Fill in the stat buffer. */
968 statbuf->st_mode = S_IFDIR | S_IRUSR | S_IRGRP | S_IROTH;
969 return 0;
970 }
971
916 /* AASSET_MODE_STREAMING is fastest here. */ 972 /* AASSET_MODE_STREAMING is fastest here. */
917 asset_desc = AAssetManager_open (asset_manager, asset, 973 asset_desc = AAssetManager_open (asset_manager, asset,
918 AASSET_MODE_STREAMING); 974 AASSET_MODE_STREAMING);
@@ -923,7 +979,7 @@ android_fstatat (int dirfd, const char *restrict pathname,
923 memset (statbuf, 0, sizeof *statbuf); 979 memset (statbuf, 0, sizeof *statbuf);
924 980
925 /* Fill in the stat buffer. */ 981 /* Fill in the stat buffer. */
926 statbuf->st_mode = S_IFREG; 982 statbuf->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH;
927 statbuf->st_size = AAsset_getLength (asset_desc); 983 statbuf->st_size = AAsset_getLength (asset_desc);
928 984
929 /* Close the asset. */ 985 /* Close the asset. */
@@ -1118,7 +1174,8 @@ android_open (const char *filename, int oflag, int mode)
1118 1174
1119 /* Fill in some information that will be reported to 1175 /* Fill in some information that will be reported to
1120 callers of android_fstat, among others. */ 1176 callers of android_fstat, among others. */
1121 android_table[fd].statb.st_mode = S_IFREG; 1177 android_table[fd].statb.st_mode
1178 = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH;;
1122 1179
1123 /* Owned by root. */ 1180 /* Owned by root. */
1124 android_table[fd].statb.st_uid = 0; 1181 android_table[fd].statb.st_uid = 0;
@@ -4023,8 +4080,21 @@ struct android_dir
4023 4080
4024 /* And the end of the files in asset_dir. */ 4081 /* And the end of the files in asset_dir. */
4025 char *asset_limit; 4082 char *asset_limit;
4083
4084 /* The next struct android_dir. */
4085 struct android_dir *next;
4086
4087 /* Path to the directory relative to /. */
4088 char *asset_file;
4089
4090 /* File descriptor used when asset_dir is set. */
4091 int fd;
4026}; 4092};
4027 4093
4094/* List of all struct android_dir's corresponding to an asset
4095 directory that are currently open. */
4096static struct android_dir *android_dirs;
4097
4028/* Like opendir. However, return an asset directory if NAME points to 4098/* Like opendir. However, return an asset directory if NAME points to
4029 an asset. */ 4099 an asset. */
4030 4100
@@ -4034,7 +4104,7 @@ android_opendir (const char *name)
4034 struct android_dir *dir; 4104 struct android_dir *dir;
4035 char *asset_dir; 4105 char *asset_dir;
4036 const char *asset_name; 4106 const char *asset_name;
4037 size_t limit; 4107 size_t limit, length;
4038 4108
4039 asset_name = android_get_asset_name (name); 4109 asset_name = android_get_asset_name (name);
4040 4110
@@ -4052,10 +4122,19 @@ android_opendir (const char *name)
4052 return NULL; 4122 return NULL;
4053 } 4123 }
4054 4124
4125 length = strlen (name);
4126
4055 dir = xmalloc (sizeof *dir); 4127 dir = xmalloc (sizeof *dir);
4056 dir->dir = NULL; 4128 dir->dir = NULL;
4057 dir->asset_dir = asset_dir; 4129 dir->asset_dir = asset_dir;
4058 dir->asset_limit = (char *) directory_tree + limit; 4130 dir->asset_limit = (char *) directory_tree + limit;
4131 dir->fd = -1;
4132 dir->asset_file = xzalloc (length + 2);
4133
4134 /* Make sure dir->asset_file is terminated with /. */
4135 strcpy (dir->asset_file, name);
4136 if (dir->asset_file[length - 1] != '/')
4137 dir->asset_file[length] = '/';
4059 4138
4060 /* Make sure dir->asset_limit is within bounds. It is a limit, 4139 /* Make sure dir->asset_limit is within bounds. It is a limit,
4061 and as such can be exactly one byte past directory_tree. */ 4140 and as such can be exactly one byte past directory_tree. */
@@ -4069,6 +4148,9 @@ android_opendir (const char *name)
4069 errno = EACCES; 4148 errno = EACCES;
4070 } 4149 }
4071 4150
4151 dir->next = android_dirs;
4152 android_dirs = dir;
4153
4072 return dir; 4154 return dir;
4073 } 4155 }
4074 4156
@@ -4086,6 +4168,26 @@ android_opendir (const char *name)
4086 return dir; 4168 return dir;
4087} 4169}
4088 4170
4171/* Like dirfd. However, value is not a real directory file descriptor
4172 if DIR is an asset directory. */
4173
4174int
4175android_dirfd (struct android_dir *dirp)
4176{
4177 int fd;
4178
4179 if (dirp->dir)
4180 return dirfd (dirp->dir);
4181 else if (dirp->fd != -1)
4182 return dirp->fd;
4183
4184 fd = open ("/dev/null", O_RDONLY | O_CLOEXEC);
4185
4186 /* Record this file descriptor in dirp. */
4187 dirp->fd = fd;
4188 return fd;
4189}
4190
4089/* Like readdir, except it understands asset directories. */ 4191/* Like readdir, except it understands asset directories. */
4090 4192
4091struct dirent * 4193struct dirent *
@@ -4152,8 +4254,29 @@ android_readdir (struct android_dir *dir)
4152void 4254void
4153android_closedir (struct android_dir *dir) 4255android_closedir (struct android_dir *dir)
4154{ 4256{
4257 struct android_dir **next, *tem;
4258
4155 if (dir->dir) 4259 if (dir->dir)
4156 closedir (dir->dir); 4260 closedir (dir->dir);
4261 else
4262 {
4263 if (dir->fd != -1)
4264 close (dir->fd);
4265
4266 /* Unlink this directory from the list of all asset manager
4267 directories. */
4268
4269 for (next = &android_dirs; (tem = *next);)
4270 {
4271 if (tem == dir)
4272 *next = dir->next;
4273 else
4274 next = &(*next)->next;
4275 }
4276
4277 /* Free the asset file name. */
4278 xfree (dir->asset_file);
4279 }
4157 4280
4158 /* There is no need to close anything else, as the directory tree 4281 /* There is no need to close anything else, as the directory tree
4159 lies in statically allocated memory. */ 4282 lies in statically allocated memory. */
@@ -4161,6 +4284,43 @@ android_closedir (struct android_dir *dir)
4161 xfree (dir); 4284 xfree (dir);
4162} 4285}
4163 4286
4287/* Subroutine used by android_fstatat. If DIRFD belongs to an open
4288 asset directory and FILE is a relative file name, then return
4289 AT_FDCWD and the absolute file name of the directory prepended to
4290 FILE in *PATHNAME. Else, return DIRFD. */
4291
4292int
4293android_lookup_asset_directory_fd (int dirfd,
4294 const char *restrict *pathname,
4295 const char *restrict file)
4296{
4297 struct android_dir *dir;
4298 static char *name;
4299
4300 if (file[0] == '/')
4301 return dirfd;
4302
4303 for (dir = android_dirs; dir; dir = dir->next)
4304 {
4305 if (dir->fd == dirfd && dirfd != -1)
4306 {
4307 if (name)
4308 xfree (name);
4309
4310 /* dir->asset_file is always separator terminated. */
4311 name = xzalloc (strlen (dir->asset_file)
4312 + strlen (file) + 1);
4313 strcpy (name, dir->asset_file);
4314 strcpy (name + strlen (dir->asset_file),
4315 file);
4316 *pathname = name;
4317 return AT_FDCWD;
4318 }
4319 }
4320
4321 return dirfd;
4322}
4323
4164 4324
4165 4325
4166/* emacs_abort implementation for Android. This logs a stack 4326/* emacs_abort implementation for Android. This logs a stack