Skip to content

Commit 3eb5a57

Browse files
authored
Add some missing musl file (#21771)
These should have been included in the v1.2.5 update (#21598). In particular `statx.c` contains the implementation of the `statx` function which has been reported as being undefined. Note that we don't actually do this by implementing a statx syscall. We simply rely on the emulation via statat.
1 parent 37e1e68 commit 3eb5a57

File tree

8 files changed

+224
-1
lines changed

8 files changed

+224
-1
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#include <sys/wait.h>
2+
#include "syscall.h"
3+
4+
#ifndef SYS_wait4
5+
hidden long __emulate_wait4(int pid, int *status, int options, void *kru, int cp)
6+
{
7+
idtype_t t;
8+
int r;
9+
siginfo_t info;
10+
11+
info.si_pid = 0;
12+
if (pid < -1) {
13+
t = P_PGID;
14+
pid = -pid;
15+
} else if (pid == -1) {
16+
t = P_ALL;
17+
} else if (pid == 0) {
18+
t = P_PGID;
19+
} else {
20+
t = P_PID;
21+
}
22+
23+
if (cp) r = __syscall_cp(SYS_waitid, t, pid, &info, options|WEXITED, kru);
24+
else r = __syscall(SYS_waitid, t, pid, &info, options|WEXITED, kru);
25+
26+
if (r<0) return r;
27+
28+
if (info.si_pid && status) {
29+
int sw=0;
30+
switch (info.si_code) {
31+
case CLD_CONTINUED:
32+
sw = 0xffff;
33+
break;
34+
case CLD_DUMPED:
35+
sw = info.si_status&0x7f | 0x80;
36+
break;
37+
case CLD_EXITED:
38+
sw = (info.si_status&0xff) << 8;
39+
break;
40+
case CLD_KILLED:
41+
sw = info.si_status&0x7f;
42+
break;
43+
case CLD_STOPPED:
44+
case CLD_TRAPPED:
45+
/* see ptrace(2); the high bits of si_status can contain */
46+
/* PTRACE_EVENT_ values which must be preserved */
47+
sw = (info.si_status << 8) + 0x7f;
48+
break;
49+
}
50+
*status = sw;
51+
}
52+
53+
return info.si_pid;
54+
}
55+
#endif
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#define _GNU_SOURCE
2+
#include <sys/uio.h>
3+
#include <unistd.h>
4+
#include "syscall.h"
5+
6+
ssize_t preadv2(int fd, const struct iovec *iov, int count, off_t ofs, int flags)
7+
{
8+
#ifdef SYS_preadv
9+
if (!flags) {
10+
if (ofs==-1) return readv(fd, iov, count);
11+
return syscall_cp(SYS_preadv, fd, iov, count,
12+
(long)(ofs), (long)(ofs>>32));
13+
}
14+
#endif
15+
return syscall_cp(SYS_preadv2, fd, iov, count,
16+
(long)(ofs), (long)(ofs>>32), flags);
17+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#define _GNU_SOURCE
2+
#include <sys/uio.h>
3+
#include <unistd.h>
4+
#include "syscall.h"
5+
6+
ssize_t pwritev2(int fd, const struct iovec *iov, int count, off_t ofs, int flags)
7+
{
8+
#ifdef SYS_pwritev
9+
if (!flags) {
10+
if (ofs==-1) return writev(fd, iov, count);
11+
return syscall_cp(SYS_pwritev, fd, iov, count,
12+
(long)(ofs), (long)(ofs>>32));
13+
}
14+
#endif
15+
return syscall_cp(SYS_pwritev2, fd, iov, count,
16+
(long)(ofs), (long)(ofs>>32), flags);
17+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#define _GNU_SOURCE
2+
#include <sys/stat.h>
3+
#include <string.h>
4+
#include <syscall.h>
5+
#include <sys/sysmacros.h>
6+
#include <errno.h>
7+
8+
int statx(int dirfd, const char *restrict path, int flags, unsigned mask, struct statx *restrict stx)
9+
{
10+
#ifdef __EMSCRIPTEN__
11+
int ret;
12+
#else
13+
int ret = __syscall(SYS_statx, dirfd, path, flags, mask, stx);
14+
15+
#ifndef SYS_fstatat
16+
return __syscall_ret(ret);
17+
#endif
18+
19+
if (ret != -ENOSYS) return __syscall_ret(ret);
20+
#endif
21+
22+
struct stat st;
23+
ret = fstatat(dirfd, path, &st, flags);
24+
if (ret) return ret;
25+
26+
stx->stx_dev_major = major(st.st_dev);
27+
stx->stx_dev_minor = minor(st.st_dev);
28+
stx->stx_ino = st.st_ino;
29+
stx->stx_mode = st.st_mode;
30+
stx->stx_nlink = st.st_nlink;
31+
stx->stx_uid = st.st_uid;
32+
stx->stx_gid = st.st_gid;
33+
stx->stx_size = st.st_size;
34+
stx->stx_blksize = st.st_blksize;
35+
stx->stx_blocks = st.st_blocks;
36+
stx->stx_atime.tv_sec = st.st_atim.tv_sec;
37+
stx->stx_atime.tv_nsec = st.st_atim.tv_nsec;
38+
stx->stx_mtime.tv_sec = st.st_mtim.tv_sec;
39+
stx->stx_mtime.tv_nsec = st.st_mtim.tv_nsec;
40+
stx->stx_ctime.tv_sec = st.st_ctim.tv_sec;
41+
stx->stx_ctime.tv_nsec = st.st_ctim.tv_nsec;
42+
stx->stx_btime = (struct statx_timestamp){.tv_sec=0, .tv_nsec=0};
43+
stx->stx_mask = STATX_BASIC_STATS;
44+
45+
return 0;
46+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#define _BSD_SOURCE
2+
#include <poll.h>
3+
#include <signal.h>
4+
#include <errno.h>
5+
#include "syscall.h"
6+
7+
#define IS32BIT(x) !((x)+0x80000000ULL>>32)
8+
#define CLAMP(x) (int)(IS32BIT(x) ? (x) : 0x7fffffffU+((0ULL+(x))>>63))
9+
10+
int ppoll(struct pollfd *fds, nfds_t n, const struct timespec *to, const sigset_t *mask)
11+
{
12+
time_t s = to ? to->tv_sec : 0;
13+
long ns = to ? to->tv_nsec : 0;
14+
#ifdef SYS_ppoll_time64
15+
int r = -ENOSYS;
16+
if (SYS_ppoll == SYS_ppoll_time64 || !IS32BIT(s))
17+
r = __syscall_cp(SYS_ppoll_time64, fds, n,
18+
to ? ((long long[]){s, ns}) : 0,
19+
mask, _NSIG/8);
20+
if (SYS_ppoll == SYS_ppoll_time64 || r != -ENOSYS)
21+
return __syscall_ret(r);
22+
s = CLAMP(s);
23+
#endif
24+
return syscall_cp(SYS_ppoll, fds, n,
25+
to ? ((long[]){s, ns}) : 0, mask, _NSIG/8);
26+
}

test/stat/test_statx.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright 2024 The Emscripten Authors. All rights reserved.
3+
* Emscripten is available under two separate licenses, the MIT license and the
4+
* University of Illinois/NCSA Open Source License. Both these licenses can be
5+
* found in the LICENSE file.
6+
*/
7+
8+
#define _GNU_SOURCE
9+
10+
#include <assert.h>
11+
#include <fcntl.h>
12+
#include <stdio.h>
13+
#include <string.h>
14+
#include <sys/stat.h>
15+
#include <unistd.h>
16+
17+
void create_file(const char *path, const char *buffer, int mode) {
18+
int fd = open(path, O_WRONLY | O_CREAT | O_EXCL, mode);
19+
assert(fd >= 0);
20+
21+
int err = write(fd, buffer, sizeof(char) * strlen(buffer));
22+
assert(err == (sizeof(char) * strlen(buffer)));
23+
24+
close(fd);
25+
}
26+
27+
void setup() {
28+
mkdir("folder", 0777);
29+
create_file("folder/file", "abcdef", 0777);
30+
symlink("file", "folder/file-link");
31+
}
32+
33+
int main() {
34+
setup();
35+
36+
int rc;
37+
struct statx buf;
38+
39+
rc = statx(AT_FDCWD, "folder", 0, STATX_ALL, &buf);
40+
assert(rc == 0);
41+
assert(S_ISDIR(buf.stx_mode));
42+
43+
rc = statx(AT_FDCWD, "folder/file", 0, STATX_ALL, &buf);
44+
assert(rc == 0);
45+
assert(S_ISREG(buf.stx_mode));
46+
47+
rc = statx(AT_FDCWD, "folder/file-link", 0, STATX_ALL, &buf);
48+
assert(rc == 0);
49+
assert(S_ISREG(buf.stx_mode));
50+
51+
rc = statx(AT_FDCWD, "folder/file-link", AT_SYMLINK_NOFOLLOW, STATX_ALL, &buf);
52+
assert(rc == 0);
53+
assert(S_ISLNK(buf.stx_mode));
54+
55+
printf("success\n");
56+
return 0;
57+
}

test/test_core.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5590,6 +5590,10 @@ def test_stat(self):
55905590
self.do_runf('stat/test_stat.c', 'success')
55915591
self.verify_in_strict_mode('test_stat.js')
55925592

5593+
def test_statx(self):
5594+
self.set_setting("FORCE_FILESYSTEM")
5595+
self.do_runf('stat/test_statx.c', 'success')
5596+
55935597
def test_fstatat(self):
55945598
self.do_runf('stat/test_fstatat.c', 'success')
55955599

tools/system_libs.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1092,6 +1092,7 @@ def get_files(self):
10921092
'memcpy.c', 'memset.c', 'memmove.c', 'getaddrinfo.c', 'getnameinfo.c',
10931093
'res_query.c', 'res_querydomain.c',
10941094
'proto.c',
1095+
'ppoll.c',
10951096
'syscall.c', 'popen.c', 'pclose.c',
10961097
'getgrouplist.c', 'initgroups.c', 'wordexp.c', 'timer_create.c',
10971098
'getentropy.c',
@@ -1232,7 +1233,7 @@ def get_files(self):
12321233

12331234
libc_files += files_in_path(
12341235
path='system/lib/libc/musl/src/linux',
1235-
filenames=['getdents.c', 'gettid.c', 'utimes.c'])
1236+
filenames=['getdents.c', 'gettid.c', 'utimes.c', 'statx.c'])
12361237

12371238
libc_files += files_in_path(
12381239
path='system/lib/libc/musl/src/sched',

0 commit comments

Comments
 (0)