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