diff --git a/egl/wayland-egl-symbols-check b/egl/wayland-egl-symbols-check index d04fd042..6adef0aa 100755 --- a/egl/wayland-egl-symbols-check +++ b/egl/wayland-egl-symbols-check @@ -14,7 +14,12 @@ if ! test -n "$NM"; then exit 99 fi -AVAIL_FUNCS="$($NM -D --format=bsd --defined-only $LIB | awk '{print $3}')" +# Assuming any system with SystemVersion.plist is a darwin-derivative and prefixes C symbols with _ +if [ -f "/System/Library/CoreServices/SystemVersion.plist" ] ; then + AVAIL_FUNCS="$($NM $LIB | awk '{print $3}' | sed 's:^_::')" +else + AVAIL_FUNCS="$($NM -D --format=bsd --defined-only $LIB | awk '{print $3}')" +fi # Official ABI, taken from the header. REQ_FUNCS="wl_egl_window_resize diff --git a/meson.build b/meson.build index b879df7b..e5af2459 100644 --- a/meson.build +++ b/meson.build @@ -19,6 +19,10 @@ cc_args = [] if host_machine.system() != 'freebsd' cc_args += ['-D_POSIX_C_SOURCE=200809L'] endif +if host_machine.system() == 'darwin' + # For CMSG_LEN(), which is an RFC 2292 addition and not part of POSIX.1-2008 + cc_args += ['-D_DARWIN_C_SOURCE'] +endif add_project_arguments(cc_args, language: 'c') compiler_flags = [ @@ -40,6 +44,7 @@ endforeach have_funcs = [ 'accept4', + 'getpeereid', 'mkostemp', 'posix_fallocate', 'prctl', @@ -69,15 +74,20 @@ endif config_h.set10('HAVE_BROKEN_MSG_CMSG_CLOEXEC', have_broken_msg_cmsg_cloexec) if get_option('libraries') - if host_machine.system() == 'freebsd' - # When building for FreeBSD, epoll(7) is provided by a userspace - # wrapper around kqueue(2). + if host_machine.system() in ['darwin', 'freebsd'] + # When building for darwin or FreeBSD, epoll(7) is provided by a + # userspace wrapper around kqueue(2). epoll_dep = dependency('epoll-shim') else # Otherwise, assume that epoll(7) is supported natively. epoll_dep = [] endif - ffi_dep = dependency('libffi') + + if host_machine.system() == 'darwin' + ffi_dep = cc.find_library('ffi') + else + ffi_dep = dependency('libffi') + endif decls = [ { 'header': 'sys/signalfd.h', 'symbol': 'SFD_CLOEXEC' }, @@ -91,11 +101,15 @@ if get_option('libraries') endif endforeach - rt_dep = [] - if not cc.has_function('clock_gettime', prefix: '#include ') - rt_dep = cc.find_library('rt') - if not cc.has_function('clock_gettime', prefix: '#include ', dependencies: rt_dep, args: cc_args) - error('clock_gettime not found') + if host_machine.system() == 'darwin' + rt_dep = [] + else + rt_dep = [] + if cc.has_function('clock_gettime', prefix: '#include ') + rt_dep = cc.find_library('rt') + if not cc.has_function('clock_gettime', prefix: '#include ', dependencies: rt_dep, args: cc_args) + error('clock_gettime not found') + endif endif endif endif diff --git a/src/connection.c b/src/connection.c index ceaeac14..af79450e 100644 --- a/src/connection.c +++ b/src/connection.c @@ -38,7 +38,11 @@ #include #include #include +#ifdef __APPLE__ +#include +#else #include +#endif #include "wayland-util.h" #include "wayland-private.h" diff --git a/src/meson.build b/src/meson.build index 9e61f3d4..7510f471 100644 --- a/src/meson.build +++ b/src/meson.build @@ -29,7 +29,12 @@ wayland_util_dep = declare_dependency( if get_option('scanner') # wayland-scanner - scanner_deps = [ dependency('expat') ] + if host_machine.system() == 'darwin' + scanner_deps = [ cc.find_library('expat') ] + else + scanner_deps = [ dependency('expat') ] + endif + scanner_args = [ '-include', 'config.h' ] if get_option('dtd_validation') diff --git a/src/wayland-os.c b/src/wayland-os.c index a9066cae..ba2c814b 100644 --- a/src/wayland-os.c +++ b/src/wayland-os.c @@ -69,16 +69,38 @@ wl_os_socket_cloexec(int domain, int type, int protocol) { int fd; +#ifdef SOCK_CLOEXEC fd = socket(domain, type | SOCK_CLOEXEC, protocol); if (fd >= 0) return fd; if (errno != EINVAL) return -1; +#endif fd = socket(domain, type, protocol); return set_cloexec_or_close(fd); } +int +wl_os_socketpair_cloexec(int domain, int type, int protocol, int sv[2]) +{ + int retval; + +#ifdef SOCK_CLOEXEC + retval = socketpair(domain, type | SOCK_CLOEXEC, protocol, sv); + if (retval >= 0) + return retval; + if (errno != EINVAL) + return -1; +#endif + + retval = socketpair(domain, type, protocol, sv); + if (set_cloexec_or_close(sv[0]) == -1 || set_cloexec_or_close(sv[1]) == -1) + retval = -1; + + return retval; +} + #if defined(__FreeBSD__) int wl_os_socket_peercred(int sockfd, uid_t *uid, gid_t *gid, pid_t *pid) @@ -115,6 +137,22 @@ wl_os_socket_peercred(int sockfd, uid_t *uid, gid_t *gid, pid_t *pid) *pid = ucred.pid; return 0; } +#elif defined(HAVE_GETPEEREID) && defined(LOCAL_PEERPID) +int +wl_os_socket_peercred(int sockfd, uid_t *uid, gid_t *gid, pid_t *pid) +{ + socklen_t len; + + if (getpeereid(sockfd, uid, gid) != 0) { + return -1; + } + + len = sizeof(pid_t); + if (getsockopt(sockfd, SOL_LOCAL, LOCAL_PEERPID, pid, &len) != 0) { + return -1; + } + return 0; +} #else #error "Don't know how to read ucred on this platform" #endif @@ -124,11 +162,13 @@ wl_os_dupfd_cloexec(int fd, int minfd) { int newfd; +#ifdef F_DUPFD_CLOEXEC newfd = fcntl(fd, F_DUPFD_CLOEXEC, minfd); if (newfd >= 0) return newfd; if (errno != EINVAL) return -1; +#endif newfd = fcntl(fd, F_DUPFD, minfd); return set_cloexec_or_close(newfd); @@ -176,7 +216,7 @@ wl_os_recvmsg_cloexec(int sockfd, struct msghdr *msg, int flags) * fix (https://cgit.freebsd.org/src/commit/?id=6ceacebdf52211). */ #pragma message("Using fallback directly since MSG_CMSG_CLOEXEC is broken.") -#else +#elif defined(MSG_CMSG_CLOEXEC) ssize_t len; len = recvmsg(sockfd, msg, flags | MSG_CMSG_CLOEXEC); diff --git a/src/wayland-os.h b/src/wayland-os.h index 068fd2fe..42e28007 100644 --- a/src/wayland-os.h +++ b/src/wayland-os.h @@ -32,6 +32,9 @@ int wl_os_socket_cloexec(int domain, int type, int protocol); +int +wl_os_socketpair_cloexec(int domain, int type, int protocol, int sv[2]); + int wl_os_socket_peercred(int sockfd, uid_t *uid, gid_t *gid, pid_t *pid); diff --git a/src/wayland-shm.c b/src/wayland-shm.c index 8fb657aa..5707a0b8 100644 --- a/src/wayland-shm.c +++ b/src/wayland-shm.c @@ -306,8 +306,10 @@ shm_create_pool(struct wl_client *client, struct wl_resource *resource, uint32_t id, int fd, int32_t size) { struct wl_shm_pool *pool; +#ifdef HAVE_MEMFD_CREATE struct stat statbuf; int seals; +#endif int prot; int flags; diff --git a/tests/client-test.c b/tests/client-test.c index 47be83fc..d3b09443 100644 --- a/tests/client-test.c +++ b/tests/client-test.c @@ -34,6 +34,7 @@ #include #include +#include "wayland-os.h" #include "wayland-private.h" #include "wayland-server.h" #include "test-runner.h" @@ -88,7 +89,7 @@ TEST(client_destroy_listener) struct client_destroy_listener a, b; int s[2]; - assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0); + assert(wl_os_socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, s) == 0); display = wl_display_create(); assert(display); client = wl_client_create(display, s[0]); diff --git a/tests/connection-test.c b/tests/connection-test.c index 9762e0da..80f4f443 100644 --- a/tests/connection-test.c +++ b/tests/connection-test.c @@ -37,6 +37,7 @@ #include #include +#include "wayland-os.h" #include "wayland-private.h" #include "test-runner.h" #include "test-compositor.h" @@ -48,7 +49,7 @@ setup(int *s) { struct wl_connection *connection; - assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0); + assert(wl_os_socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, s) == 0); connection = wl_connection_create(s[0]); assert(connection); @@ -181,8 +182,8 @@ struct marshal_data { static void setup_marshal_data(struct marshal_data *data) { - assert(socketpair(AF_UNIX, - SOCK_STREAM | SOCK_CLOEXEC, 0, data->s) == 0); + assert(wl_os_socketpair_cloexec(AF_UNIX, + SOCK_STREAM, 0, data->s) == 0); data->read_connection = wl_connection_create(data->s[0]); assert(data->read_connection); data->write_connection = wl_connection_create(data->s[1]); @@ -824,7 +825,7 @@ TEST(request_bogus_size) for (bogus_size = 11; bogus_size >= 0; bogus_size--) { fprintf(stderr, "* bogus size %d\n", bogus_size); - assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0); + assert(wl_os_socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, s) == 0); display = wl_display_create(); assert(display); client = wl_client_create(display, s[0]); diff --git a/tests/os-wrappers-test.c b/tests/os-wrappers-test.c index 8d8c3ab9..50218594 100644 --- a/tests/os-wrappers-test.c +++ b/tests/os-wrappers-test.c @@ -47,6 +47,7 @@ static int fall_back; +#ifdef __ELF__ /* Play nice with sanitizers * * Sanitizers need to intercept syscalls in the compiler run-time library. As @@ -71,6 +72,13 @@ static int fall_back; #define REAL(func) (__interceptor_ ## func) ? \ __interceptor_ ## func : \ (__typeof__(&__interceptor_ ## func))dlsym(RTLD_NEXT, #func) +#else +#define DECL(ret_type, func, ...) \ + static ret_type (*real_ ## func)(__VA_ARGS__); \ + static int wrapped_calls_ ## func; + +#define REAL(func) (__typeof__(real_ ## func)) dlsym(RTLD_NEXT, #func) +#endif DECL(int, socket, int, int, int); DECL(int, fcntl, int, int, ...); @@ -92,10 +100,12 @@ socket(int domain, int type, int protocol) { wrapped_calls_socket++; +#ifdef SOCK_CLOEXEC if (fall_back && (type & SOCK_CLOEXEC)) { errno = EINVAL; return -1; } +#endif return real_socket(domain, type, protocol); } @@ -141,10 +151,12 @@ recvmsg(int sockfd, struct msghdr *msg, int flags) { wrapped_calls_recvmsg++; +#ifdef MSG_CMSG_CLOEXEC if (fall_back && (flags & MSG_CMSG_CLOEXEC)) { errno = EINVAL; return -1; } +#endif return real_recvmsg(sockfd, msg, flags); } @@ -179,7 +191,11 @@ do_os_wrappers_socket_cloexec(int n) * Must have 2 calls if falling back, but must also allow * falling back without a forced fallback. */ +#ifdef SOCK_CLOEXEC assert(wrapped_calls_socket > n); +#else + assert(wrapped_calls_socket == 1); +#endif exec_fd_leak_check(nr_fds); } @@ -253,8 +269,8 @@ struct marshal_data { static void setup_marshal_data(struct marshal_data *data) { - assert(socketpair(AF_UNIX, - SOCK_STREAM | SOCK_CLOEXEC, 0, data->s) == 0); + assert(wl_os_socketpair_cloexec(AF_UNIX, + SOCK_STREAM, 0, data->s) == 0); data->read_connection = wl_connection_create(data->s[0]); assert(data->read_connection); @@ -342,9 +358,10 @@ do_os_wrappers_recvmsg_cloexec(int n) struct marshal_data data; data.nr_fds_begin = count_open_fds(); -#if HAVE_BROKEN_MSG_CMSG_CLOEXEC +#if HAVE_BROKEN_MSG_CMSG_CLOEXEC || !defined(MSG_CMSG_CLOEXEC) /* We call the fallback directly on FreeBSD versions with a broken - * MSG_CMSG_CLOEXEC, so we don't call the local recvmsg() wrapper. */ + * MSG_CMSG_CLOEXEC or platforms without MSG_CMSG_CLOEXEC, so we + * don't call the local recvmsg() wrapper. */ data.wrapped_calls = 0; #else data.wrapped_calls = n; diff --git a/tests/resources-test.c b/tests/resources-test.c index fa6ba2b2..ca4595cb 100644 --- a/tests/resources-test.c +++ b/tests/resources-test.c @@ -28,6 +28,7 @@ #include #include +#include "wayland-os.h" #include "wayland-server.h" #include "test-runner.h" @@ -40,7 +41,7 @@ TEST(create_resource_tst) int s[2]; uint32_t id; - assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0); + assert(wl_os_socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, s) == 0); display = wl_display_create(); assert(display); client = wl_client_create(display, s[0]); @@ -111,7 +112,7 @@ TEST(destroy_res_tst) .notify = &destroy_notify }; - assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0); + assert(wl_os_socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, s) == 0); display = wl_display_create(); assert(display); client = wl_client_create(display, s[0]); @@ -159,7 +160,7 @@ TEST(create_resource_with_same_id) int s[2]; uint32_t id; - assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0); + assert(wl_os_socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, s) == 0); display = wl_display_create(); assert(display); client = wl_client_create(display, s[0]); diff --git a/tests/test-compositor.c b/tests/test-compositor.c index 49d76d6d..3c0d537f 100644 --- a/tests/test-compositor.c +++ b/tests/test-compositor.c @@ -93,7 +93,7 @@ get_socket_name(void) gettimeofday(&tv, NULL); snprintf(retval, sizeof retval, "wayland-test-%d-%ld%ld", - getpid(), tv.tv_sec, tv.tv_usec); + (int)getpid(), (long)tv.tv_sec, (long)tv.tv_usec); return retval; } @@ -510,7 +510,7 @@ static const struct wl_registry_listener registry_listener = NULL }; -struct client *client_connect() +struct client *client_connect(void) { struct wl_registry *reg; struct client *c = calloc(1, sizeof *c); diff --git a/tests/test-runner.c b/tests/test-runner.c index d07dab15..7a61ecba 100644 --- a/tests/test-runner.c +++ b/tests/test-runner.c @@ -63,7 +63,12 @@ static int timeouts_enabled = 1; /* set to one if the output goes to the terminal */ static int is_atty = 0; +#ifdef __APPLE__ +extern const struct test __start_test_section __asm("section$start$__RODATA$test_section"); +extern const struct test __stop_test_section __asm("section$end$__RODATA$test_section"); +#else extern const struct test __start_test_section, __stop_test_section; +#endif static const struct test * find_test(const char *name) @@ -308,6 +313,12 @@ is_debugger_attached(void) return rc; } +#else +static int +is_debugger_attached(void) +{ + return 0; +} #endif int main(int argc, char *argv[]) diff --git a/tests/test-runner.h b/tests/test-runner.h index d0734009..2024fa13 100644 --- a/tests/test-runner.h +++ b/tests/test-runner.h @@ -31,6 +31,12 @@ #include +#ifdef __APPLE__ +#define TEST_SECTION "__RODATA,test_section" +#else +#define TEST_SECTION "test_section" +#endif + struct test { const char *name; void (*run)(void); @@ -41,7 +47,7 @@ struct test { static void name(void); \ \ const struct test test##name \ - __attribute__ ((used, section ("test_section"))) = { \ + __attribute__ ((used, section (TEST_SECTION))) = { \ #name, name, 0 \ }; \ \ @@ -51,7 +57,7 @@ struct test { static void name(void); \ \ const struct test test##name \ - __attribute__ ((used, section ("test_section"))) = { \ + __attribute__ ((used, section (TEST_SECTION))) = { \ #name, name, 1 \ }; \ \