]> git.proxmox.com Git - wasi-libc.git/blob - libc-bottom-half/cloudlibc/src/libc/sys/stat/stat_impl.h
d1a26fdadd82f8023b4a0e88c6e823cd86f005bf
[wasi-libc.git] / libc-bottom-half / cloudlibc / src / libc / sys / stat / stat_impl.h
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
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 #ifdef __wasilibc_unmodified_upstream
28 static_assert(sizeof(in->st_dev) == sizeof(out->st_dev), "Size mismatch");
29 static_assert(sizeof(in->st_ino) == sizeof(out->st_ino), "Size mismatch");
30 static_assert(sizeof(in->st_filetype) == sizeof(out->__st_filetype),
31 "Size mismatch");
32 #else
33 static_assert(sizeof(in->dev) == sizeof(out->st_dev), "Size mismatch");
34 static_assert(sizeof(in->ino) == sizeof(out->st_ino), "Size mismatch");
35 /*
36 * The non-standard __st_filetype field appears to only be used for shared
37 * memory, which we don't currently support.
38 */
39 #endif
40 #ifdef __wasilibc_unmodified_upstream
41 static_assert(sizeof(in->st_nlink) == sizeof(out->st_nlink), "Size mismatch");
42 static_assert(sizeof(in->st_size) == sizeof(out->st_size), "Size mismatch");
43 #else
44 /* nlink_t is 64-bit on wasm32, following the x32 ABI. */
45 static_assert(sizeof(in->nlink) <= sizeof(out->st_nlink), "Size shortfall");
46 static_assert(sizeof(in->size) == sizeof(out->st_size), "Size mismatch");
47 #endif
48
49 *out = (struct stat){
50 #ifdef __wasilibc_unmodified_upstream
51 #define COPY_FIELD(field) .field = in->field
52 COPY_FIELD(st_dev),
53 COPY_FIELD(st_ino),
54 .__st_filetype = in->st_filetype,
55 COPY_FIELD(st_nlink),
56 COPY_FIELD(st_size),
57 #undef COPY_FIELD
58 #define COPY_TIMESPEC(field) .field = timestamp_to_timespec(in->field)
59 COPY_TIMESPEC(st_atim),
60 COPY_TIMESPEC(st_mtim),
61 COPY_TIMESPEC(st_ctim),
62 #undef COPY_TIMESPEC
63 #else
64 .st_dev = in->dev,
65 .st_ino = in->ino,
66 .st_nlink = in->nlink,
67 .st_size = in->size,
68 .st_atim = timestamp_to_timespec(in->atim),
69 .st_mtim = timestamp_to_timespec(in->mtim),
70 .st_ctim = timestamp_to_timespec(in->ctim),
71 #endif
72 };
73
74 // Convert file type to legacy types encoded in st_mode.
75 #ifdef __wasilibc_unmodified_upstream
76 switch (in->st_filetype) {
77 #else
78 switch (in->filetype) {
79 #endif
80 case __WASI_FILETYPE_BLOCK_DEVICE:
81 out->st_mode |= S_IFBLK;
82 break;
83 case __WASI_FILETYPE_CHARACTER_DEVICE:
84 out->st_mode |= S_IFCHR;
85 break;
86 case __WASI_FILETYPE_DIRECTORY:
87 out->st_mode |= S_IFDIR;
88 break;
89 case __WASI_FILETYPE_REGULAR_FILE:
90 out->st_mode |= S_IFREG;
91 break;
92 case __WASI_FILETYPE_SOCKET_DGRAM:
93 case __WASI_FILETYPE_SOCKET_STREAM:
94 out->st_mode |= S_IFSOCK;
95 break;
96 case __WASI_FILETYPE_SYMBOLIC_LINK:
97 out->st_mode |= S_IFLNK;
98 break;
99 }
100 }
101
102 static inline bool utimens_get_timestamps(const struct timespec *times,
103 #ifdef __wasilibc_unmodified_upstream // fstat
104 __wasi_filestat_t *fs,
105 __wasi_fsflags_t *flags) {
106 #else
107 __wasi_timestamp_t *st_atim,
108 __wasi_timestamp_t *st_mtim,
109 __wasi_fstflags_t *flags) {
110 #endif
111 if (times == NULL) {
112 // Update both timestamps.
113 #ifdef __wasilibc_unmodified_upstream // fstat
114 *flags = __WASI_FILESTAT_ATIM_NOW | __WASI_FILESTAT_MTIM_NOW;
115 #else
116 *flags = __WASI_FSTFLAGS_ATIM_NOW | __WASI_FSTFLAGS_MTIM_NOW;
117 #endif
118 } else {
119 // Set individual timestamps.
120 *flags = 0;
121 switch (times[0].tv_nsec) {
122 case UTIME_NOW:
123 #ifdef __wasilibc_unmodified_upstream // fstat
124 *flags |= __WASI_FILESTAT_ATIM_NOW;
125 #else
126 *flags |= __WASI_FSTFLAGS_ATIM_NOW;
127 #endif
128 break;
129 case UTIME_OMIT:
130 break;
131 default:
132 #ifdef __wasilibc_unmodified_upstream // fstat
133 *flags |= __WASI_FILESTAT_ATIM;
134 if (!timespec_to_timestamp_exact(&times[0], &fs->st_atim))
135 #else
136 *flags |= __WASI_FSTFLAGS_ATIM;
137 if (!timespec_to_timestamp_exact(&times[0], st_atim))
138 #endif
139 return false;
140 break;
141 }
142
143 switch (times[1].tv_nsec) {
144 case UTIME_NOW:
145 #ifdef __wasilibc_unmodified_upstream // fstat
146 *flags |= __WASI_FILESTAT_MTIM_NOW;
147 #else
148 *flags |= __WASI_FSTFLAGS_MTIM_NOW;
149 #endif
150 break;
151 case UTIME_OMIT:
152 break;
153 default:
154 #ifdef __wasilibc_unmodified_upstream // fstat
155 *flags |= __WASI_FILESTAT_MTIM;
156 if (!timespec_to_timestamp_exact(&times[1], &fs->st_mtim))
157 #else
158 *flags |= __WASI_FSTFLAGS_MTIM;
159 if (!timespec_to_timestamp_exact(&times[1], st_mtim))
160 #endif
161 return false;
162 break;
163 }
164 }
165 return true;
166 }
167
168 #endif