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