1 // Copyright (c) 2015-2016 Nuxi, https://nuxi.nl/
3 // SPDX-License-Identifier: BSD-2-Clause
5 #include <common/errno.h>
14 #ifdef __wasilibc_unmodified_upstream // fstat
15 static_assert(O_APPEND
== __WASI_FDFLAG_APPEND
, "Value mismatch");
16 static_assert(O_DSYNC
== __WASI_FDFLAG_DSYNC
, "Value mismatch");
17 static_assert(O_NONBLOCK
== __WASI_FDFLAG_NONBLOCK
, "Value mismatch");
18 static_assert(O_RSYNC
== __WASI_FDFLAG_RSYNC
, "Value mismatch");
19 static_assert(O_SYNC
== __WASI_FDFLAG_SYNC
, "Value mismatch");
21 static_assert(O_APPEND
== __WASI_FDFLAGS_APPEND
, "Value mismatch");
22 static_assert(O_DSYNC
== __WASI_FDFLAGS_DSYNC
, "Value mismatch");
23 static_assert(O_NONBLOCK
== __WASI_FDFLAGS_NONBLOCK
, "Value mismatch");
24 static_assert(O_RSYNC
== __WASI_FDFLAGS_RSYNC
, "Value mismatch");
25 static_assert(O_SYNC
== __WASI_FDFLAGS_SYNC
, "Value mismatch");
28 #ifdef __wasilibc_unmodified_upstream // fstat
29 static_assert(O_CREAT
>> 12 == __WASI_O_CREAT
, "Value mismatch");
30 static_assert(O_DIRECTORY
>> 12 == __WASI_O_DIRECTORY
, "Value mismatch");
31 static_assert(O_EXCL
>> 12 == __WASI_O_EXCL
, "Value mismatch");
32 static_assert(O_TRUNC
>> 12 == __WASI_O_TRUNC
, "Value mismatch");
34 static_assert(O_CREAT
>> 12 == __WASI_OFLAGS_CREAT
, "Value mismatch");
35 static_assert(O_DIRECTORY
>> 12 == __WASI_OFLAGS_DIRECTORY
, "Value mismatch");
36 static_assert(O_EXCL
>> 12 == __WASI_OFLAGS_EXCL
, "Value mismatch");
37 static_assert(O_TRUNC
>> 12 == __WASI_OFLAGS_TRUNC
, "Value mismatch");
40 int openat(int fd
, const char *path
, int oflag
, ...) {
41 #ifdef __wasilibc_unmodified_upstream // fstat
43 return __wasilibc_openat_nomode(fd
, path
, oflag
);
46 int __wasilibc_openat_nomode(int fd
, const char *path
, int oflag
) {
48 // Compute rights corresponding with the access modes provided.
49 // Attempt to obtain all rights, except the ones that contradict the
50 // access mode provided to openat().
51 #ifdef __wasilibc_unmodified_upstream // Let the WASI implementation check this instead.
52 __wasi_rights_t min
= 0;
55 #ifdef __wasilibc_unmodified_upstream // fstat
56 ~(__WASI_RIGHT_FD_DATASYNC
| __WASI_RIGHT_FD_READ
|
57 __WASI_RIGHT_FD_WRITE
| __WASI_RIGHT_FILE_ALLOCATE
|
58 __WASI_RIGHT_FILE_READDIR
| __WASI_RIGHT_FILE_STAT_FPUT_SIZE
|
60 ~(__WASI_RIGHTS_FD_DATASYNC
| __WASI_RIGHTS_FD_READ
|
61 __WASI_RIGHTS_FD_WRITE
| __WASI_RIGHTS_FD_ALLOCATE
|
62 __WASI_RIGHTS_FD_READDIR
| __WASI_RIGHTS_FD_FILESTAT_SET_SIZE
|
64 #ifdef __wasilibc_unmodified_upstream // RIGHT_MEM_MAP_EXEC
65 __WASI_RIGHT_MEM_MAP_EXEC
);
69 switch (oflag
& O_ACCMODE
) {
73 if ((oflag
& O_RDONLY
) != 0) {
74 #ifdef __wasilibc_unmodified_upstream // Let the WASI implementation check this instead.
75 min
|= (oflag
& O_DIRECTORY
) == 0 ? __WASI_RIGHT_FD_READ
76 : __WASI_RIGHT_FILE_READDIR
;
78 #ifdef __wasilibc_unmodified_upstream // RIGHT_MEM_MAP_EXEC
79 max
|= __WASI_RIGHT_FD_READ
| __WASI_RIGHT_FILE_READDIR
|
80 __WASI_RIGHT_MEM_MAP_EXEC
;
82 max
|= __WASI_RIGHTS_FD_READ
| __WASI_RIGHTS_FD_READDIR
;
85 if ((oflag
& O_WRONLY
) != 0) {
86 #ifdef __wasilibc_unmodified_upstream // Let the WASI implementation check this instead.
87 min
|= __WASI_RIGHT_FD_WRITE
;
88 if ((oflag
& O_APPEND
) == 0)
89 min
|= __WASI_RIGHT_FD_SEEK
;
91 #ifdef __wasilibc_unmodified_upstream // fstat
92 max
|= __WASI_RIGHT_FD_DATASYNC
| __WASI_RIGHT_FD_WRITE
|
93 __WASI_RIGHT_FILE_ALLOCATE
|
94 __WASI_RIGHT_FILE_STAT_FPUT_SIZE
;
96 max
|= __WASI_RIGHTS_FD_DATASYNC
| __WASI_RIGHTS_FD_WRITE
|
97 __WASI_RIGHTS_FD_ALLOCATE
|
98 __WASI_RIGHTS_FD_FILESTAT_SET_SIZE
;
103 #ifdef __wasilibc_unmodified_upstream // RIGHT_PROC_EXEC
104 min
|= __WASI_RIGHT_PROC_EXEC
;
113 #ifdef __wasilibc_unmodified_upstream // Let the WASI implementation check this instead.
114 assert((min
& max
) == min
&&
115 "Minimal rights should be a subset of the maximum");
118 // Ensure that we can actually obtain the minimal rights needed.
119 __wasi_fdstat_t fsb_cur
;
120 #ifdef __wasilibc_unmodified_upstream
121 __wasi_errno_t error
= __wasi_fd_stat_get(fd
, &fsb_cur
);
123 __wasi_errno_t error
= __wasi_fd_fdstat_get(fd
, &fsb_cur
);
129 #ifdef __wasilibc_unmodified_upstream // Let the WASI implementation check this instead.
130 if (fsb_cur
.fs_filetype
!= __WASI_FILETYPE_DIRECTORY
) {
134 if ((min
& fsb_cur
.fs_rights_inheriting
) != min
) {
140 // Path lookup properties.
141 #ifdef __wasilibc_unmodified_upstream // split out __wasi_lookup_t
142 __wasi_lookup_t lookup
= {.fd
= fd
, .flags
= 0};
144 __wasi_lookupflags_t lookup_flags
= 0;
146 if ((oflag
& O_NOFOLLOW
) == 0)
147 #ifdef __wasilibc_unmodified_upstream // split out __wasi_lookup_t
148 lookup
.flags
|= __WASI_LOOKUP_SYMLINK_FOLLOW
;
150 lookup_flags
|= __WASI_LOOKUPFLAGS_SYMLINK_FOLLOW
;
153 // Open file with appropriate rights.
154 #ifdef __wasilibc_unmodified_upstream // split out __wasi_lookup_t and __wasi_fdstat_t
155 __wasi_fdstat_t fsb_new
= {
156 .fs_flags
= oflag
& 0xfff,
157 .fs_rights_base
= max
& fsb_cur
.fs_rights_inheriting
,
158 .fs_rights_inheriting
= fsb_cur
.fs_rights_inheriting
,
161 error
= __wasi_file_open(lookup
, path
, strlen(path
),
162 (oflag
>> 12) & 0xfff, &fsb_new
, &newfd
);
164 __wasi_fdflags_t fs_flags
= oflag
& 0xfff;
165 __wasi_rights_t fs_rights_base
= max
& fsb_cur
.fs_rights_inheriting
;
166 __wasi_rights_t fs_rights_inheriting
= fsb_cur
.fs_rights_inheriting
;
168 error
= __wasi_path_open(fd
, lookup_flags
, path
, strlen(path
),
169 (oflag
>> 12) & 0xfff,
170 fs_rights_base
, fs_rights_inheriting
, fs_flags
,
174 #ifdef __wasilibc_unmodified_upstream // split out __wasi_lookup_t
175 errno
= errno_fixup_directory(lookup
.fd
, error
);
177 errno
= errno_fixup_directory(fd
, error
);