1 // Copyright (c) 2015-2017 Nuxi, https://nuxi.nl/
2 //
3 // SPDX-License-Identifier: BSD-2-Clause
4
5 #ifndef SYS_STAT_STAT_IMPL_H
6 #define SYS_STAT_STAT_IMPL_H
7
8 #include <common/time.h>
9
10 #include <sys/stat.h>
11
12 #include <assert.h>
13 #include <wasi/api.h>
14 #include <stdbool.h>
15
16 static_assert(S_ISBLK(S_IFBLK), "Value mismatch");
17 static_assert(S_ISCHR(S_IFCHR), "Value mismatch");
18 static_assert(S_ISDIR(S_IFDIR), "Value mismatch");
19 static_assert(S_ISFIFO(S_IFIFO), "Value mismatch");
20 static_assert(S_ISLNK(S_IFLNK), "Value mismatch");
21 static_assert(S_ISREG(S_IFREG), "Value mismatch");
22 static_assert(S_ISSOCK(S_IFSOCK), "Value mismatch");
23
to_public_stat(const __wasi_filestat_t * in,struct stat * out)24 static inline void to_public_stat(const __wasi_filestat_t *in,
25 struct stat *out) {
26 // Ensure that we don't truncate any values.
27 static_assert(sizeof(in->dev) == sizeof(out->st_dev), "Size mismatch");
28 static_assert(sizeof(in->ino) == sizeof(out->st_ino), "Size mismatch");
29 /*
30 * The non-standard __st_filetype field appears to only be used for shared
31 * memory, which we don't currently support.
32 */
33 /* nlink_t is 64-bit on wasm32, following the x32 ABI. */
34 static_assert(sizeof(in->nlink) <= sizeof(out->st_nlink), "Size shortfall");
35 static_assert(sizeof(in->size) == sizeof(out->st_size), "Size mismatch");
36
37 *out = (struct stat){
38 .st_dev = in->dev,
39 .st_ino = in->ino,
40 .st_nlink = in->nlink,
41 .st_size = in->size,
42 .st_atim = timestamp_to_timespec(in->atim),
43 .st_mtim = timestamp_to_timespec(in->mtim),
44 .st_ctim = timestamp_to_timespec(in->ctim),
45 };
46
47 // Convert file type to legacy types encoded in st_mode.
48 switch (in->filetype) {
49 case __WASI_FILETYPE_BLOCK_DEVICE:
50 out->st_mode |= S_IFBLK;
51 break;
52 case __WASI_FILETYPE_CHARACTER_DEVICE:
53 out->st_mode |= S_IFCHR;
54 break;
55 case __WASI_FILETYPE_DIRECTORY:
56 out->st_mode |= S_IFDIR;
57 break;
58 case __WASI_FILETYPE_REGULAR_FILE:
59 out->st_mode |= S_IFREG;
60 break;
61 case __WASI_FILETYPE_SOCKET_DGRAM:
62 case __WASI_FILETYPE_SOCKET_STREAM:
63 out->st_mode |= S_IFSOCK;
64 break;
65 case __WASI_FILETYPE_SYMBOLIC_LINK:
66 out->st_mode |= S_IFLNK;
67 break;
68 }
69 }
70
utimens_get_timestamps(const struct timespec * times,__wasi_timestamp_t * st_atim,__wasi_timestamp_t * st_mtim,__wasi_fstflags_t * flags)71 static inline bool utimens_get_timestamps(const struct timespec *times,
72 __wasi_timestamp_t *st_atim,
73 __wasi_timestamp_t *st_mtim,
74 __wasi_fstflags_t *flags) {
75 if (times == NULL) {
76 // Update both timestamps.
77 *flags = __WASI_FSTFLAGS_ATIM_NOW | __WASI_FSTFLAGS_MTIM_NOW;
78 } else {
79 // Set individual timestamps.
80 *flags = 0;
81 switch (times[0].tv_nsec) {
82 case UTIME_NOW:
83 *flags |= __WASI_FSTFLAGS_ATIM_NOW;
84 break;
85 case UTIME_OMIT:
86 break;
87 default:
88 *flags |= __WASI_FSTFLAGS_ATIM;
89 if (!timespec_to_timestamp_exact(×[0], st_atim))
90 return false;
91 break;
92 }
93
94 switch (times[1].tv_nsec) {
95 case UTIME_NOW:
96 *flags |= __WASI_FSTFLAGS_MTIM_NOW;
97 break;
98 case UTIME_OMIT:
99 break;
100 default:
101 *flags |= __WASI_FSTFLAGS_MTIM;
102 if (!timespec_to_timestamp_exact(×[1], st_mtim))
103 return false;
104 break;
105 }
106 }
107 return true;
108 }
109
110 #endif
111