feat(posix): add Windows compatibility backend

Introduce the Win32 backend and POSIX shim headers used by the POSIX SITL platform on Windows hosts.

The backend provides filesystem, networking, process, time, termios, dlfcn, console, and errno translation hooks. Common platform types are also adjusted for MSVC/MinGW portability, including atomics, visibility, ioctl pointer values, task priorities, semaphores, and platform exit.

Signed-off-by: Nuno Marques <n.marques21@hotmail.com>
This commit is contained in:
Nuno Marques
2026-04-27 15:24:51 -07:00
parent a484e1b166
commit c49699fb5d
78 changed files with 9668 additions and 33 deletions
@@ -58,6 +58,10 @@
#include <stdbool.h>
#include <stdint.h>
#if defined(_MSC_VER) && !defined(__clang__)
# include <atomic>
#endif
#if defined(__PX4_NUTTX)
# include <nuttx/irq.h>
#endif // __PX4_NUTTX
@@ -73,7 +77,9 @@ public:
#if defined(__PX4_POSIX)
// Ensure that all operations are lock-free, so that 'atomic' can be used from
// IRQ handlers. This might not be required everywhere though.
# if !defined(_MSC_VER) || defined(__clang__)
static_assert(__atomic_always_lock_free(sizeof(T), 0), "atomic is not lock-free for the given type T");
# endif
#endif // __PX4_POSIX
atomic() = default;
@@ -95,7 +101,11 @@ public:
} else
#endif // __PX4_NUTTX
{
#if defined(_MSC_VER) && !defined(__clang__)
return _value.load(std::memory_order_seq_cst);
#else
return __atomic_load_n(&_value, __ATOMIC_SEQ_CST);
#endif
}
}
@@ -114,7 +124,11 @@ public:
} else
#endif // __PX4_NUTTX
{
#if defined(_MSC_VER) && !defined(__clang__)
_value.store(value, std::memory_order_seq_cst);
#else
__atomic_store(&_value, &value, __ATOMIC_SEQ_CST);
#endif
}
}
@@ -136,7 +150,11 @@ public:
} else
#endif // __PX4_NUTTX
{
#if defined(_MSC_VER) && !defined(__clang__)
return _value.fetch_add(num, std::memory_order_seq_cst);
#else
return __atomic_fetch_add(&_value, num, __ATOMIC_SEQ_CST);
#endif
}
}
@@ -158,7 +176,11 @@ public:
} else
#endif // __PX4_NUTTX
{
#if defined(_MSC_VER) && !defined(__clang__)
return _value.fetch_sub(num, std::memory_order_seq_cst);
#else
return __atomic_fetch_sub(&_value, num, __ATOMIC_SEQ_CST);
#endif
}
}
@@ -180,7 +202,11 @@ public:
} else
#endif // __PX4_NUTTX
{
#if defined(_MSC_VER) && !defined(__clang__)
return _value.fetch_and(num, std::memory_order_seq_cst);
#else
return __atomic_fetch_and(&_value, num, __ATOMIC_SEQ_CST);
#endif
}
}
@@ -202,7 +228,11 @@ public:
} else
#endif // __PX4_NUTTX
{
#if defined(_MSC_VER) && !defined(__clang__)
return _value.fetch_xor(num, std::memory_order_seq_cst);
#else
return __atomic_fetch_xor(&_value, num, __ATOMIC_SEQ_CST);
#endif
}
}
@@ -224,7 +254,11 @@ public:
} else
#endif // __PX4_NUTTX
{
#if defined(_MSC_VER) && !defined(__clang__)
return _value.fetch_or(num, std::memory_order_seq_cst);
#else
return __atomic_fetch_or(&_value, num, __ATOMIC_SEQ_CST);
#endif
}
}
@@ -246,7 +280,18 @@ public:
} else
#endif // __PX4_NUTTX
{
#if defined(_MSC_VER) && !defined(__clang__)
T expected = _value.load(std::memory_order_seq_cst);
T desired;
do {
desired = static_cast<T>(~(expected & num));
} while (!_value.compare_exchange_weak(expected, desired, std::memory_order_seq_cst, std::memory_order_seq_cst));
return expected;
#else
return __atomic_fetch_nand(&_value, num, __ATOMIC_SEQ_CST);
#endif
}
}
@@ -279,12 +324,20 @@ public:
} else
#endif // __PX4_NUTTX
{
#if defined(_MSC_VER) && !defined(__clang__)
return _value.compare_exchange_strong(*expected, desired, std::memory_order_seq_cst, std::memory_order_seq_cst);
#else
return __atomic_compare_exchange(&_value, expected, &desired, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
#endif
}
}
private:
#if defined(_MSC_VER) && !defined(__clang__)
std::atomic<T> _value {};
#else
T _value {};
#endif
};
using atomic_int = atomic<int>;
@@ -52,10 +52,21 @@
/* Define PX4_ISFINITE */
#ifdef __cplusplus
#if defined(_MSC_VER) && !defined(__clang__)
#include <cmath>
static inline bool PX4_ISFINITE(float x) { return std::isfinite(x); }
static inline bool PX4_ISFINITE(double x) { return std::isfinite(x); }
#else
static inline constexpr bool PX4_ISFINITE(float x) { return __builtin_isfinite(x); }
static inline constexpr bool PX4_ISFINITE(double x) { return __builtin_isfinite(x); }
#endif
#else
#if defined(_MSC_VER) && !defined(__clang__)
#include <math.h>
#define PX4_ISFINITE(x) isfinite(x)
#else
#define PX4_ISFINITE(x) __builtin_isfinite(x)
#endif
#endif /* __cplusplus */
#if defined(__PX4_NUTTX)
@@ -82,6 +93,12 @@ static inline constexpr bool PX4_ISFINITE(double x) { return __builtin_isfinite(
#define O_BINARY 0
#endif
// S_IRUSR / S_IWUSR / S_IRGRP / ... live in <sys/stat.h>. Most POSIX
// consumers of this header pull it in transitively via <fcntl.h>, but
// MinGW's fcntl.h doesn't — include it explicitly so the PX4_O_MODE_*
// macros below always resolve.
#include <sys/stat.h>
// mode for open with O_CREAT
#define PX4_O_MODE_777 (S_IRWXU | S_IRWXG | S_IRWXO)
#define PX4_O_MODE_666 (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH )
@@ -109,6 +126,19 @@ __END_DECLS
****************************************************************************/
#define OK 0
// <wingdi.h> defines ERROR as 0 for its GDI error codes and pulls it in
// transitively from <windows.h>. Undefine before redefining so we match
// the historical PX4 POSIX semantics.
#ifdef ERROR
#undef ERROR
#endif
// Windows <winbase.h> also leaks IGNORE (value 0, used by the
// NEEDED_ACCESS / ServiceControl surface). PX4 uses IGNORE as an enum
// member in ControlAllocator::FailureMode — drop the Windows macro
// since no PX4 code consumes the Win32 meaning.
#ifdef IGNORE
#undef IGNORE
#endif
#define ERROR -1
#define MAX_RAND 32767
@@ -0,0 +1,69 @@
/****************************************************************************
*
* Copyright (c) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file exit.h
*
* Platform-level process exit hook.
*/
#pragma once
#include <visibility.h>
#if defined(__PX4_WINDOWS)
#include <px4_windows/platform.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
static inline void px4_platform_exit(int status) noreturn_function;
static inline void px4_platform_exit(int status)
{
#if defined(__PX4_WINDOWS)
px4_windows_exit(status);
#else
system_exit(status);
#endif
#if defined(_MSC_VER) && !defined(__clang__)
__assume(0);
#else
__builtin_unreachable();
#endif
}
#ifdef __cplusplus
}
#endif
@@ -117,7 +117,7 @@ __EXPORT int px4_open(const char *path, int flags, ...);
__EXPORT int px4_close(int fd);
__EXPORT ssize_t px4_read(int fd, void *buffer, size_t buflen);
__EXPORT ssize_t px4_write(int fd, const void *buffer, size_t buflen);
__EXPORT int px4_ioctl(int fd, int cmd, unsigned long arg);
__EXPORT int px4_ioctl(int fd, int cmd, uintptr_t arg);
__EXPORT int px4_poll(px4_pollfd_struct_t *fds, unsigned int nfds, int timeout);
__EXPORT int px4_access(const char *pathname, int mode);
__EXPORT px4_task_t px4_getpid(void);
@@ -131,7 +131,7 @@ __END_DECLS
// we often run out of stack space when pointers are larger than 4 bytes.
// Double the stack size on posix when we're on a 64-bit architecture.
// Most full-scale OS use 1-4K of memory from the stack themselves
#define PX4_STACK_ADJUSTED(_s) (_s * (__SIZEOF_POINTER__ >> 2) + PX4_STACK_OVERHEAD)
#define PX4_STACK_ADJUSTED(_s) (_s * (sizeof(void *) >> 2) + PX4_STACK_OVERHEAD)
__BEGIN_DECLS
@@ -73,6 +73,15 @@ typedef int px4_task_t;
#define SCHED_PRIORITY_MIN sched_get_priority_min(SCHED_FIFO)
#define SCHED_PRIORITY_DEFAULT (((sched_get_priority_max(SCHED_FIFO) - sched_get_priority_min(SCHED_FIFO)) / 2) + sched_get_priority_min(SCHED_FIFO))
#elif defined(__PX4_WINDOWS)
/* winpthreads maps SCHED_FIFO/SCHED_OTHER onto Win32 thread priorities.
* sched_get_priority_{max,min}(SCHED_FIFO) works but returns a narrow
* range (15..-15). Use fixed values consistent with the rest of PX4. */
#define SCHED_PRIORITY_MAX 15
#define SCHED_PRIORITY_MIN (-15)
#define SCHED_PRIORITY_DEFAULT 0
#elif defined(__PX4_QURT)
#define SCHED_PRIORITY_MAX 255
@@ -25,20 +25,25 @@ __END_DECLS
#endif
#if defined(ENABLE_LOCKSTEP_SCHEDULER)
#if defined(ENABLE_LOCKSTEP_SCHEDULER) || defined(__PX4_WINDOWS)
__BEGIN_DECLS
__EXPORT int px4_usleep(useconds_t usec);
__EXPORT unsigned int px4_sleep(unsigned int seconds);
#if defined(ENABLE_LOCKSTEP_SCHEDULER)
__EXPORT int px4_pthread_cond_timedwait(pthread_cond_t *cond,
pthread_mutex_t *mutex,
const struct timespec *abstime);
#endif
__END_DECLS
#else
#define px4_usleep system_usleep
#define px4_sleep system_sleep
#define px4_pthread_cond_timedwait system_pthread_cond_timedwait
#endif
#if !defined(ENABLE_LOCKSTEP_SCHEDULER)
#define px4_pthread_cond_timedwait system_pthread_cond_timedwait
#endif
@@ -49,6 +49,11 @@
#include <limits.h>
#include <string.h>
#if defined(__PX4_POSIX)
#include <pthread.h>
#include <unistd.h>
#endif
using namespace time_literals;
namespace px4
@@ -274,8 +279,8 @@ WorkQueueManagerRun(int, char **)
#elif defined(__PX4_POSIX)
// On posix system , the desired stacksize round to the nearest multiplier of the system pagesize
// It is a requirement of the pthread_attr_setstacksize* function
const unsigned int page_size = sysconf(_SC_PAGESIZE);
const size_t stacksize_adj = math::max((int)PTHREAD_STACK_MIN, PX4_STACK_ADJUSTED(wq->stacksize));
const size_t page_size = static_cast<size_t>(sysconf(_SC_PAGESIZE));
const size_t stacksize_adj = math::max(static_cast<size_t>(PTHREAD_STACK_MIN), static_cast<size_t>(PX4_STACK_ADJUSTED(wq->stacksize)));
const size_t stacksize = (stacksize_adj + page_size - (stacksize_adj % page_size));
#endif
@@ -304,15 +309,33 @@ WorkQueueManagerRun(int, char **)
PX4_ERR("getting sched param for %s failed (%i)", wq->name, ret_getschedparam);
}
// schedule policy FIFO
int ret_setschedpolicy = pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
// schedule policy FIFO — fall back to SCHED_OTHER on platforms
// where SCHED_FIFO is not available to unprivileged threads
// (winpthreads on MinGW is one such case). The work queues
// still work correctly at SCHED_OTHER priority.
int sched_policy = SCHED_FIFO;
int ret_setschedpolicy = pthread_attr_setschedpolicy(&attr, sched_policy);
if (ret_setschedpolicy != 0) {
PX4_ERR("failed to set sched policy SCHED_FIFO (%i)", ret_setschedpolicy);
sched_policy = SCHED_OTHER;
ret_setschedpolicy = pthread_attr_setschedpolicy(&attr, sched_policy);
}
// priority
param.sched_priority = sched_priority;
if (ret_setschedpolicy != 0) {
PX4_ERR("failed to set sched policy (%i)", ret_setschedpolicy);
}
// priority — clamp to the policy's valid range, otherwise
// pthread_attr_setschedparam rejects the value and the
// thread ends up at whatever default the library picks.
const int max_prio = sched_get_priority_max(sched_policy);
const int min_prio = sched_get_priority_min(sched_policy);
int effective_prio = sched_priority;
if (effective_prio > max_prio) { effective_prio = max_prio; }
if (effective_prio < min_prio) { effective_prio = min_prio; }
param.sched_priority = effective_prio;
int ret_setschedparam = pthread_attr_setschedparam(&attr, &param);
if (ret_setschedparam != 0) {
+1 -1
View File
@@ -209,7 +209,7 @@ uORB::DeviceNode::write(cdev::file_t *filp, const char *buffer, size_t buflen)
}
int
uORB::DeviceNode::ioctl(cdev::file_t *filp, int cmd, unsigned long arg)
uORB::DeviceNode::ioctl(cdev::file_t *filp, int cmd, uintptr_t arg)
{
switch (cmd) {
case ORBIOCUPDATED: {
+1 -1
View File
@@ -114,7 +114,7 @@ public:
/**
* IOCTL control for the subscriber.
*/
int ioctl(cdev::file_t *filp, int cmd, unsigned long arg) override;
int ioctl(cdev::file_t *filp, int cmd, uintptr_t arg) override;
/**
* Method to publish a data to this node.
+3 -3
View File
@@ -302,7 +302,7 @@ orb_advert_t uORB::Manager::orb_advertise_multi(const struct orb_metadata *meta,
/* get the advertiser handle and close the node */
orb_advert_t advertiser;
int result = px4_ioctl(fd, ORBIOCGADVERTISER, (unsigned long)&advertiser);
int result = px4_ioctl(fd, ORBIOCGADVERTISER, (uintptr_t)&advertiser);
px4_close(fd);
if (result == PX4_ERROR) {
@@ -397,7 +397,7 @@ int uORB::Manager::orb_check(int handle, bool *updated)
{
/* Set to false here so that if `px4_ioctl` fails to false. */
*updated = false;
return px4_ioctl(handle, ORBIOCUPDATED, (unsigned long)(uintptr_t)updated);
return px4_ioctl(handle, ORBIOCUPDATED, (uintptr_t)updated);
}
int uORB::Manager::orb_set_interval(int handle, unsigned interval)
@@ -407,7 +407,7 @@ int uORB::Manager::orb_set_interval(int handle, unsigned interval)
int uORB::Manager::orb_get_interval(int handle, unsigned *interval)
{
int ret = px4_ioctl(handle, ORBIOCGETINTERVAL, (unsigned long)interval);
int ret = px4_ioctl(handle, ORBIOCGETINTERVAL, (uintptr_t)interval);
*interval /= 1000;
return ret;
}
+3 -3
View File
@@ -102,7 +102,7 @@ orb_advert_t uORB::Manager::orb_advertise_multi(const struct orb_metadata *meta,
/* get the advertiser handle and close the node */
orb_advert_t advertiser;
int result = px4_ioctl(fd, ORBIOCGADVERTISER, (unsigned long)&advertiser);
int result = px4_ioctl(fd, ORBIOCGADVERTISER, (uintptr_t)&advertiser);
px4_close(fd);
if (result == PX4_ERROR) {
@@ -177,7 +177,7 @@ int uORB::Manager::orb_check(int handle, bool *updated)
{
/* Set to false here so that if `px4_ioctl` fails to false. */
*updated = false;
return px4_ioctl(handle, ORBIOCUPDATED, (unsigned long)(uintptr_t)updated);
return px4_ioctl(handle, ORBIOCUPDATED, (uintptr_t)updated);
}
int uORB::Manager::orb_set_interval(int handle, unsigned interval)
@@ -187,7 +187,7 @@ int uORB::Manager::orb_set_interval(int handle, unsigned interval)
int uORB::Manager::orb_get_interval(int handle, unsigned *interval)
{
int ret = px4_ioctl(handle, ORBIOCGETINTERVAL, (unsigned long)interval);
int ret = px4_ioctl(handle, ORBIOCGETINTERVAL, (uintptr_t)interval);
*interval /= 1000;
return ret;
}
@@ -0,0 +1,84 @@
/****************************************************************************
*
* Copyright (c) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file platform.h
*
* Public Windows-host hooks for the POSIX platform implementation.
*/
#pragma once
#include <visibility.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Restore the console modes captured during Windows platform startup.
*
* PX4 enables virtual-terminal output and may switch the input console into a
* raw-ish mode for the pxh shell. This must run before process teardown so a
* native console, a Wine-hosted terminal, or a parent shell does not inherit
* stale input flags.
*/
void px4_windows_restore_console_modes(void);
/**
* @brief Drop console input that was queued while PX4 was shutting down.
*
* Wine can leave bytes for control sequences or buffered pxh input pending in
* the Linux terminal after Ctrl+C. The shutdown path calls this before
* returning control to the parent shell.
*/
void px4_windows_discard_pending_input(void);
/**
* @brief Release Windows console resources owned by the PX4 process.
*
* Native Windows builds use this as the last console cleanup step; under Wine
* it complements the terminal-mode restore and input discard hooks above.
*/
void px4_windows_release_console(void);
/**
* @brief Exit PX4 after running Windows-specific console cleanup.
*
* @param status Process exit code passed to the C runtime after cleanup.
*/
void px4_windows_exit(int status) noreturn_function;
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,43 @@
/****************************************************************************
*
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file Windows.h
*
* MinGW-w64 only ships the lowercase <windows.h>, but a lot of
* Windows-targeted code (including Micro-XRCE-DDS-Client) writes
* #include <Windows.h>. On case-sensitive Linux filesystems that fails
* when cross-compiling. This header is on the include search path
* ahead of the MinGW sysroot and just forwards to the real header.
*/
#pragma once
#include <windows.h>
@@ -0,0 +1,116 @@
/****************************************************************************
*
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file afunix.h
*
* The Windows SDK's afunix.h is intentionally small: it defines the AF_UNIX
* socket address payload (`SOCKADDR_UN`, `PSOCKADDR_UN`, `UNIX_PATH_MAX`) and
* the AF_UNIX-specific WSAIoctl constants. Older MinGW sysroots do not ship
* that header at all, while newer ones may grow it over time. Mirror the
* native Windows SDK surface when present, provide a compatible fallback when
* absent, and layer the common POSIX convenience aliases (`sockaddr_un`,
* `SUN_LEN`) on top.
*/
#pragma once
#ifndef _WIN32
# error "afunix.h shim only valid on Windows"
#endif
#include <stddef.h>
#include <string.h>
#include <winsock2.h>
#if defined(__has_include_next)
# if __has_include_next(<afunix.h>)
# include_next <afunix.h>
# endif
#endif
#ifndef _AFUNIX_
#define _AFUNIX_
#ifndef AF_UNIX
#define AF_UNIX 1
#endif
#ifndef PF_UNIX
#define PF_UNIX AF_UNIX
#endif
#ifndef UNIX_PATH_MAX
#define UNIX_PATH_MAX 108
#endif
/**
* @brief AF_UNIX socket address compatible with the Windows SDK definition.
*
* The typedef aliases mirror the SDK names so code can use either POSIX
* `struct sockaddr_un` or Windows `SOCKADDR_UN`.
*/
typedef struct sockaddr_un {
ADDRESS_FAMILY sun_family; /* AF_UNIX */
char sun_path[UNIX_PATH_MAX]; /* pathname */
} SOCKADDR_UN, *PSOCKADDR_UN;
#ifndef SIO_AF_UNIX_GETPEERPID
#define SIO_AF_UNIX_GETPEERPID _WSAIOR(IOC_VENDOR, 256)
#endif
#ifndef SIO_AF_UNIX_SETBINDPARENTPATH
#define SIO_AF_UNIX_SETBINDPARENTPATH _WSAIOW(IOC_VENDOR, 257)
#endif
#ifndef SIO_AF_UNIX_SETCONNPARENTPATH
#define SIO_AF_UNIX_SETCONNPARENTPATH _WSAIOW(IOC_VENDOR, 258)
#endif
#endif /* _AFUNIX_ */
#ifdef __cplusplus
extern "C" {
#endif
#ifndef _PX4_SOCKADDR_UN_ALIAS_DEFINED
#define _PX4_SOCKADDR_UN_ALIAS_DEFINED
/** @brief POSIX alias for struct sockaddr_un. */
typedef struct sockaddr_un sockaddr_un;
#endif
#ifndef SUN_LEN
#define SUN_LEN(ptr) ((socklen_t)(offsetof(struct sockaddr_un, sun_path) + strlen((ptr)->sun_path)))
#endif
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,75 @@
/****************************************************************************
*
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file arpa/inet.h
*
* Re-export Winsock's address-conversion surface through the POSIX include
* path and provide the classic BSD helpers that Windows does not ship:
* `inet_aton`, `inet_ntoa_r`, `inet_network`, `inet_makeaddr`,
* `inet_lnaof`, and `inet_netof`.
*/
#pragma once
#ifndef _WIN32
# error "arpa/inet.h shim only valid on Windows"
#endif
#include <stddef.h>
#include <netinet/in.h>
#ifdef __cplusplus
extern "C" {
#endif
/** @brief Parse an IPv4 address string into struct in_addr. */
int inet_aton(const char *cp, struct in_addr *inp);
/** @brief Thread-safe inet_ntoa() variant writing into caller storage. */
char *inet_ntoa_r(struct in_addr in, char *buf, size_t buflen);
/** @brief Parse a classful IPv4 network number. */
in_addr_t inet_network(const char *cp);
/** @brief Return the local-network portion of a classful IPv4 address. */
in_addr_t inet_lnaof(struct in_addr in);
/** @brief Return the classful network portion of an IPv4 address. */
in_addr_t inet_netof(struct in_addr in);
/** @brief Compose an IPv4 address from classful network and host parts. */
struct in_addr inet_makeaddr(in_addr_t net, in_addr_t host);
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,314 @@
/****************************************************************************
*
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file dirent.h
*
* MinGW ships a <dirent.h> wrapper over FindFirstFile, but its `struct
* dirent` is a subset of POSIX: no `d_type`, no DT_REG/DT_DIR. PX4
* (mavlink_ftp, logger) relies on `d_type` to tell files apart from
* directories at iteration time without a second stat().
*
* Replace MinGW's header entirely with a POSIX-shaped wrapper that
* populates d_type from the Win32 attributes already carried by
* WIN32_FIND_DATA.
*/
#pragma once
#include <windows.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#ifndef NAME_MAX
#define NAME_MAX 260
#endif
/* POSIX d_type values. We only populate DT_DIR / DT_REG; anything the
* Win32 attributes don't distinguish falls through to DT_UNKNOWN. */
#define DT_UNKNOWN 0
#define DT_FIFO 1
#define DT_CHR 2
#define DT_DIR 4
#define DT_BLK 6
#define DT_REG 8
#define DT_LNK 10
#define DT_SOCK 12
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Directory entry returned by readdir().
*
* The fields match the POSIX/BSD layout expected by PX4 callers. d_type is
* derived from WIN32_FIND_DATA attributes so code can distinguish regular
* files, directories, and reparse points without an extra stat() call.
*/
struct dirent {
unsigned long d_ino;
long d_off;
unsigned short d_reclen;
unsigned short d_namlen;
unsigned char d_type;
char d_name[NAME_MAX + 1];
};
#define d_fileno d_ino
/**
* @brief Opaque directory stream backed by FindFirstFileA/FindNextFileA.
*/
typedef struct px4_dir_shim {
HANDLE handle;
WIN32_FIND_DATAA find_data;
struct dirent entry;
int first;
long offset;
char pattern[MAX_PATH];
} DIR;
/**
* @brief Open a directory stream.
*
* @param name Directory path.
* @return Directory stream, or NULL with errno set.
*/
static inline DIR *opendir(const char *name)
{
if (!name) { errno = EINVAL; return NULL; }
DIR *d = (DIR *)calloc(1, sizeof(DIR));
if (!d) { errno = ENOMEM; return NULL; }
/* Translate "foo" -> "foo\*" so FindFirstFile enumerates the
* directory's contents rather than matching the directory itself. */
int n = snprintf(d->pattern, sizeof(d->pattern), "%s\\*", name);
if (n <= 0 || (size_t)n >= sizeof(d->pattern)) {
free(d);
errno = ENAMETOOLONG;
return NULL;
}
d->handle = FindFirstFileA(d->pattern, &d->find_data);
if (d->handle == INVALID_HANDLE_VALUE) {
free(d);
errno = ENOENT;
return NULL;
}
d->first = 1;
d->offset = 0;
return d;
}
/**
* @brief Return the next directory entry.
*
* @return Pointer owned by @p d and overwritten by the next readdir() call, or
* NULL at end of directory or on error.
*/
static inline struct dirent *readdir(DIR *d)
{
if (!d) { errno = EBADF; return NULL; }
if (d->first) {
d->first = 0;
} else if (!FindNextFileA(d->handle, &d->find_data)) {
return NULL; /* end of directory */
}
strncpy(d->entry.d_name, d->find_data.cFileName, NAME_MAX);
d->entry.d_name[NAME_MAX] = '\0';
d->entry.d_off = d->offset++;
d->entry.d_reclen = (unsigned short)strlen(d->entry.d_name);
d->entry.d_namlen = d->entry.d_reclen;
if (d->find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
d->entry.d_type = DT_DIR;
} else if (d->find_data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
d->entry.d_type = DT_LNK;
} else {
d->entry.d_type = DT_REG;
}
return &d->entry;
}
/** @brief Close a directory stream and free its resources. */
static inline int closedir(DIR *d)
{
if (!d) { errno = EBADF; return -1; }
if (d->handle != INVALID_HANDLE_VALUE) {
FindClose(d->handle);
}
free(d);
return 0;
}
/** @brief Rewind a directory stream to the first entry. */
static inline void rewinddir(DIR *d)
{
if (!d) { return; }
if (d->handle != INVALID_HANDLE_VALUE) {
FindClose(d->handle);
}
d->handle = FindFirstFileA(d->pattern, &d->find_data);
d->first = (d->handle != INVALID_HANDLE_VALUE) ? 1 : 0;
d->offset = 0;
}
/** @brief Return the current logical directory offset. */
static inline long telldir(DIR *d)
{
if (!d) {
errno = EBADF;
return -1;
}
return d->offset;
}
/** @brief Seek to a logical offset previously returned by telldir(). */
static inline void seekdir(DIR *d, long loc)
{
if (!d || loc < 0) {
return;
}
rewinddir(d);
while (d->offset < loc) {
if (!readdir(d)) {
break;
}
}
}
/** @brief Sort directory entries lexicographically by d_name. */
static inline int alphasort(const struct dirent **a, const struct dirent **b)
{
return strcoll((*a)->d_name, (*b)->d_name);
}
/** @brief Version-aware sort placeholder; currently identical to alphasort(). */
static inline int versionsort(const struct dirent **a, const struct dirent **b)
{
return alphasort(a, b);
}
/**
* @brief Read a directory into an allocated, optionally filtered/sorted list.
*
* The caller owns the returned array and each entry in it, matching POSIX
* scandir() ownership rules.
*
* @return Number of entries on success, or -1 with errno set.
*/
static inline int scandir(const char *dirp, struct dirent ***namelist,
int (*select)(const struct dirent *),
int (*compar)(const struct dirent **, const struct dirent **))
{
if (!namelist) {
errno = EINVAL;
return -1;
}
*namelist = NULL;
DIR *dir = opendir(dirp);
if (!dir) {
return -1;
}
size_t count = 0;
size_t capacity = 0;
struct dirent **list = NULL;
struct dirent *entry = NULL;
while ((entry = readdir(dir)) != NULL) {
if (select && !select(entry)) {
continue;
}
if (count == capacity) {
size_t next_capacity = capacity ? capacity * 2 : 16;
struct dirent **next = (struct dirent **)realloc(list, next_capacity * sizeof(*next));
if (!next) {
for (size_t i = 0; i < count; ++i) {
free(list[i]);
}
free(list);
closedir(dir);
errno = ENOMEM;
return -1;
}
list = next;
capacity = next_capacity;
}
struct dirent *copy = (struct dirent *)malloc(sizeof(*copy));
if (!copy) {
for (size_t i = 0; i < count; ++i) {
free(list[i]);
}
free(list);
closedir(dir);
errno = ENOMEM;
return -1;
}
*copy = *entry;
list[count++] = copy;
}
closedir(dir);
if (compar && count > 1) {
qsort(list, count, sizeof(*list), (int (*)(const void *, const void *))compar);
}
*namelist = list;
return (int)count;
}
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,122 @@
/****************************************************************************
*
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file dlfcn.h
*
* The systemcmds/dyn module uses dlopen/dlsym to load .so plugins at
* runtime. On Windows we translate to LoadLibraryA / GetProcAddress /
* FreeLibrary. Modes are mostly ignored - Windows has no lazy/now,
* global/local distinction comparable to RTLD_* at the API level.
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#define RTLD_LAZY 0x0001
#define RTLD_NOW 0x0002
#define RTLD_GLOBAL 0x0100
#define RTLD_LOCAL 0x0000
#define RTLD_NODELETE 0x1000
#define RTLD_NOLOAD 0x0004
#define RTLD_DEEPBIND 0x0008
#define RTLD_DEFAULT ((void *)0)
#define RTLD_NEXT ((void *)-1)
/**
* @brief Load a dynamic library using Windows LoadLibraryA semantics.
*
* @param filename Library path. A NULL filename is accepted for source
* compatibility but has no portable Windows equivalent.
* @param flag POSIX RTLD_* mode bits. The shim accepts them for API
* compatibility; Windows binding semantics are selected by the
* loader, not by these flags.
* @return Library handle on success, NULL on failure. Use dlerror() for text.
*/
void *dlopen(const char *filename, int flag);
/**
* @brief Unload a library handle returned by dlopen().
*
* @return 0 on success, -1 on failure with dlerror() text set.
*/
int dlclose(void *handle);
/**
* @brief Look up an exported symbol in a library.
*
* @param handle Handle returned by dlopen().
* @param symbol Export name to resolve.
* @return Symbol address on success, NULL on failure.
*/
void *dlsym(void *handle, const char *symbol);
/**
* @brief Fetch and clear the thread-local dynamic-loader error string.
*
* @return Last loader error string, or NULL if no error is pending.
*/
char *dlerror(void);
/**
* @brief POSIX dladdr information container.
*
* Windows does not expose all fields with POSIX fidelity, but keeping this
* type allows diagnostics and third-party code to compile.
*/
typedef struct {
const char *dli_fname;
void *dli_fbase;
const char *dli_sname;
void *dli_saddr;
} Dl_info;
/**
* @brief Resolve best-effort module/symbol information for an address.
*
* @return Non-zero on success, 0 on failure.
*/
int dladdr(const void *addr, Dl_info *info);
/**
* @brief Versioned symbol lookup compatibility entry point.
*
* Windows exports are not ELF-versioned, so the implementation ignores
* @p version and delegates to dlsym().
*/
void *dlvsym(void *handle, const char *symbol, const char *version);
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,332 @@
/****************************************************************************
*
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file fcntl.h
*
* MinGW-w64 ships a minimal <fcntl.h> (O_RDONLY / O_BINARY / O_CREAT /
* etc.) but none of the POSIX fcntl() operations - F_GETFL, F_SETFL,
* F_GETFD, F_SETFD, O_NONBLOCK - and no fcntl() function. PX4 uses
* these only to toggle non-blocking I/O, so we satisfy the interface
* and route the one semantically meaningful op (O_NONBLOCK) onto
* ioctlsocket(FIONBIO) / _setmode as appropriate.
*/
#pragma once
#if defined(_MSC_VER) && !defined(__clang__)
#if defined(__has_include)
# if __has_include(<../ucrt/fcntl.h>)
# include <../ucrt/fcntl.h>
# endif
#endif
#include <io.h>
#include <stdio.h>
#ifndef O_RDONLY
#define O_RDONLY 0x0000
#endif
#ifndef O_WRONLY
#define O_WRONLY 0x0001
#endif
#ifndef O_RDWR
#define O_RDWR 0x0002
#endif
#ifndef O_APPEND
#define O_APPEND 0x0008
#endif
#ifndef O_CREAT
#define O_CREAT 0x0100
#endif
#ifndef O_TRUNC
#define O_TRUNC 0x0200
#endif
#ifndef O_EXCL
#define O_EXCL 0x0400
#endif
#ifndef O_TEXT
#define O_TEXT 0x4000
#endif
#ifndef O_BINARY
#define O_BINARY 0x8000
#endif
#else
#include_next <fcntl.h>
#endif
#include <windows.h>
#include <winsock2.h>
#include <io.h>
#include <errno.h>
#include <stdarg.h>
#include <string.h>
/* <windows.h> (pulled in transitively by <winsock2.h>) leaks a handful
* of all-caps macros that collide with PX4 identifiers. Undefine them
* centrally here - this header sits at the top of posix.h's include
* chain, so every PX4 translation unit that touches winsock goes
* through these undefs before any C++ code uses the names. */
/* wingdi.h defines ERROR as 0, winbase.h defines IGNORE as 0, winnt.h
* defines OPTIONAL as empty. All three clash with identifiers PX4 uses
* (ERROR=-1 from defines.h, FailureMode::IGNORE enumerator, and
* `OPTIONAL` function-argument annotations in third-party code). Strip
* the Windows leak, then - to cover the case where defines.h was
* already processed earlier in this TU - restore PX4's ERROR. */
#ifdef ERROR
#undef ERROR
#endif
#if defined(__PX4_POSIX)
#define ERROR -1
#endif
#ifdef IGNORE
#undef IGNORE
#endif
#ifdef OPTIONAL
#undef OPTIONAL
#endif
#ifndef F_GETFD
#define F_GETFD 1
#endif
#ifndef F_DUPFD
#define F_DUPFD 0
#endif
#ifndef F_DUPFD_CLOEXEC
#define F_DUPFD_CLOEXEC 1030
#endif
#ifndef F_SETFD
#define F_SETFD 2
#endif
#ifndef F_GETFL
#define F_GETFL 3
#endif
#ifndef F_SETFL
#define F_SETFL 4
#endif
#ifndef F_GETLK
#define F_GETLK 5
#endif
#ifndef F_SETLK
#define F_SETLK 6
#endif
#ifndef F_SETLKW
#define F_SETLKW 7
#endif
#ifndef F_RDLCK
#define F_RDLCK 0
#endif
#ifndef F_WRLCK
#define F_WRLCK 1
#endif
#ifndef F_UNLCK
#define F_UNLCK 2
#endif
#ifndef FD_CLOEXEC
#define FD_CLOEXEC 1
#endif
#ifndef AT_FDCWD
#define AT_FDCWD (-100)
#endif
#ifndef AT_SYMLINK_NOFOLLOW
#define AT_SYMLINK_NOFOLLOW 0x100
#endif
#ifndef AT_REMOVEDIR
#define AT_REMOVEDIR 0x200
#endif
#ifndef O_CLOEXEC
#define O_CLOEXEC 0
#endif
#ifndef O_DIRECTORY
#define O_DIRECTORY 0
#endif
#ifndef O_NOFOLLOW
#define O_NOFOLLOW 0
#endif
#ifndef O_SYNC
#define O_SYNC 0
#endif
#ifndef O_DSYNC
#define O_DSYNC O_SYNC
#endif
/**
* @brief POSIX advisory byte-range lock descriptor.
*
* Windows has no fcntl-style locking;
* F_GETLK/F_SETLK are implemented below via LockFileEx/UnlockFileEx,
* which lock a byte range of a HANDLE. PX4 uses the "whole file"
* convention (l_start=0, l_len=0) for server singleton enforcement;
* that maps cleanly onto a max-range LockFileEx call.
*/
#ifndef _PX4_STRUCT_FLOCK_DEFINED
#define _PX4_STRUCT_FLOCK_DEFINED
struct flock {
short l_type; /* F_RDLCK / F_WRLCK / F_UNLCK */
short l_whence; /* SEEK_SET / SEEK_CUR / SEEK_END */
long l_start;
long l_len; /* 0 == lock through EOF */
int l_pid;
};
#endif
/* O_NONBLOCK isn't defined by MinGW's fcntl.h. Pick a high bit that
* does not collide with the O_* flags MinGW does define. */
#ifndef O_NONBLOCK
#if defined(_MSC_VER) && !defined(__clang__)
#define O_NONBLOCK 0x200000
#else
#define O_NONBLOCK 0x4000
#endif
#endif
/* POSIX terminal-control flag; Windows has no controlling terminal
* concept, so we accept the flag and ignore it. */
#ifndef O_NOCTTY
#define O_NOCTTY 0
#endif
#ifndef O_NDELAY
#define O_NDELAY O_NONBLOCK
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief POSIX fcntl() compatibility subset.
*
* Supported operations are the descriptor/status queries PX4 uses,
* FD_CLOEXEC acceptance, O_NONBLOCK enablement for Winsock sockets, and
* advisory file locking through LockFileEx.
*
* @return 0 or a positive query value on success, -1 with errno set on failure.
*/
static inline int fcntl(int fd, int cmd, ...)
{
switch (cmd) {
case F_GETFL:
case F_GETFD:
/* No file-descriptor flag storage on Windows CRT fds. Pretend
* we got back 0 - PX4 only OR's O_NONBLOCK onto the result
* before handing it back via F_SETFL. */
return 0;
case F_SETFL: {
va_list ap;
va_start(ap, cmd);
int flags = va_arg(ap, int);
va_end(ap);
if (flags & O_NONBLOCK) {
/* Socket fds live in a separate namespace on winsock -
* ioctlsocket works on SOCKET handles, which the CRT
* stores directly in its int fds via _open_osfhandle. */
u_long mode = 1;
if (ioctlsocket((SOCKET)fd, FIONBIO, &mode) == 0) {
return 0;
}
errno = EBADF;
return -1;
}
return 0;
}
case F_SETFD:
/* FD_CLOEXEC has no Win32 analog - close-on-exec is the
* default when bInheritHandle is false, which is the CRT
* default. Accept the call so code compiles. */
return 0;
case F_GETLK:
case F_SETLK:
case F_SETLKW: {
va_list ap;
va_start(ap, cmd);
struct flock *fl = va_arg(ap, struct flock *);
va_end(ap);
if (!fl) { errno = EINVAL; return -1; }
HANDLE h = (HANDLE)_get_osfhandle(fd);
if (h == INVALID_HANDLE_VALUE) { errno = EBADF; return -1; }
/* l_len == 0 means "lock through EOF" in POSIX. Use the max
* range LockFileEx accepts (2^63-1) so the byte-range lock
* effectively covers the whole file. */
DWORD off_lo = (DWORD)fl->l_start;
DWORD off_hi = 0;
DWORD len_lo = fl->l_len ? (DWORD)fl->l_len : 0xFFFFFFFFu;
DWORD len_hi = fl->l_len ? 0 : 0x7FFFFFFFu;
OVERLAPPED ov;
memset(&ov, 0, sizeof(ov));
ov.Offset = off_lo;
ov.OffsetHigh = off_hi;
if (cmd == F_GETLK) {
/* Try to acquire non-blocking; if it succeeds no conflict
* exists, so release and report F_UNLCK. If it fails with
* ERROR_LOCK_VIOLATION something else holds a lock. */
DWORD flags = LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY;
if (LockFileEx(h, flags, 0, len_lo, len_hi, &ov)) {
UnlockFileEx(h, 0, len_lo, len_hi, &ov);
fl->l_type = F_UNLCK;
} else if (GetLastError() == ERROR_LOCK_VIOLATION
|| GetLastError() == ERROR_IO_PENDING) {
fl->l_type = F_WRLCK;
fl->l_pid = 0;
} else {
errno = EACCES;
return -1;
}
return 0;
}
if (fl->l_type == F_UNLCK) {
if (UnlockFileEx(h, 0, len_lo, len_hi, &ov)) { return 0; }
errno = EACCES;
return -1;
}
DWORD flags = LOCKFILE_EXCLUSIVE_LOCK;
if (cmd == F_SETLK) { flags |= LOCKFILE_FAIL_IMMEDIATELY; }
if (LockFileEx(h, flags, 0, len_lo, len_hi, &ov)) { return 0; }
errno = (GetLastError() == ERROR_LOCK_VIOLATION) ? EAGAIN : EACCES;
return -1;
}
default:
errno = EINVAL;
return -1;
}
}
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,184 @@
/****************************************************************************
*
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file getopt.h
*
* Minimal getopt/getopt_long shim for native Windows builds.
*/
#pragma once
#if defined(_MSC_VER) && !defined(__clang__)
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
#define no_argument 0
#define required_argument 1
#define optional_argument 2
/** @brief getopt_long() option descriptor. */
struct option {
const char *name;
int has_arg;
int *flag;
int val;
};
static char *optarg = NULL;
static int optind = 1;
static int opterr = 1;
static int optopt = 0;
static int px4_getopt_nextchar = 1;
/**
* @brief Parse short options from argv.
*
* This is a compact implementation sufficient for PX4 command-line parsers in
* native MSVC builds. MinGW uses its system getopt implementation.
*/
static inline int getopt(int argc, char *const argv[], const char *optstring)
{
optarg = NULL;
if (optind >= argc || !argv[optind] || argv[optind][0] != '-' || argv[optind][1] == '\0') {
return -1;
}
if (strcmp(argv[optind], "--") == 0) {
++optind;
px4_getopt_nextchar = 1;
return -1;
}
const char opt = argv[optind][px4_getopt_nextchar];
const char *match = strchr(optstring, opt);
optopt = opt;
if (!match) {
if (argv[optind][++px4_getopt_nextchar] == '\0') {
++optind;
px4_getopt_nextchar = 1;
}
return '?';
}
if (match[1] == ':') {
if (argv[optind][px4_getopt_nextchar + 1] != '\0') {
optarg = &argv[optind][px4_getopt_nextchar + 1];
++optind;
px4_getopt_nextchar = 1;
} else if (optind + 1 < argc) {
optarg = argv[++optind];
++optind;
px4_getopt_nextchar = 1;
} else {
++optind;
px4_getopt_nextchar = 1;
return (optstring[0] == ':') ? ':' : '?';
}
} else {
if (argv[optind][++px4_getopt_nextchar] == '\0') {
++optind;
px4_getopt_nextchar = 1;
}
}
return opt;
}
/**
* @brief Parse long and short options from argv.
*
* Supports exact long-option matches and required arguments. Optional long
* arguments are accepted as source-compatible descriptors but treated like
* no-argument options unless supplied with '='.
*/
static inline int getopt_long(int argc, char *const argv[], const char *optstring,
const struct option *longopts, int *longindex)
{
if (optind < argc && argv[optind] && strncmp(argv[optind], "--", 2) == 0 && argv[optind][2] != '\0') {
const char *name = argv[optind] + 2;
const char *value = strchr(name, '=');
const size_t name_len = value ? (size_t)(value - name) : strlen(name);
for (int i = 0; longopts && longopts[i].name; ++i) {
if (strncmp(name, longopts[i].name, name_len) == 0 && longopts[i].name[name_len] == '\0') {
if (longindex) {
*longindex = i;
}
if (longopts[i].has_arg == required_argument) {
if (value) {
optarg = (char *)(value + 1);
} else if (optind + 1 < argc) {
optarg = argv[++optind];
} else {
++optind;
return '?';
}
} else {
optarg = NULL;
}
++optind;
if (longopts[i].flag) {
*longopts[i].flag = longopts[i].val;
return 0;
}
return longopts[i].val;
}
}
}
return getopt(argc, argv, optstring);
}
#ifdef __cplusplus
}
#endif
#else
#include_next <getopt.h>
#endif
@@ -0,0 +1,91 @@
/****************************************************************************
*
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file grp.h
*
* Windows has no /etc/group. Like pwd.h, this shim synthesizes a
* minimal current-user group entry so POSIX consumers can compile and
* basic lookups continue to work.
*/
#pragma once
#include <stddef.h>
#include <sys/types.h>
#ifndef _PX4_UID_T_DEFINED_SHIM
#define _PX4_UID_T_DEFINED_SHIM
typedef unsigned int uid_t;
typedef unsigned int gid_t;
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief POSIX group entry synthesized for the current Windows user.
*/
struct group {
char *gr_name;
char *gr_passwd;
gid_t gr_gid;
char **gr_mem;
};
/** @brief Return a static group entry for the requested GID when available. */
struct group *getgrgid(gid_t gid);
/** @brief Return a static group entry for the requested group name. */
struct group *getgrnam(const char *name);
/**
* @brief Reentrant GID lookup.
*
* @return 0 on success or not found; @p result is NULL when no entry matches.
* Returns an errno value when @p buf is too small or arguments are
* invalid.
*/
int getgrgid_r(gid_t gid, struct group *grp, char *buf, size_t buflen, struct group **result);
/**
* @brief Reentrant group-name lookup.
*
* @return 0 on success or not found; @p result is NULL when no entry matches.
* Returns an errno value when @p buf is too small or arguments are
* invalid.
*/
int getgrnam_r(const char *name, struct group *grp, char *buf, size_t buflen, struct group **result);
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,105 @@
/****************************************************************************
*
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file libgen.h
*
* basename()/dirname() helpers for Windows builds.
*/
#pragma once
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Return the final path component in place.
*
* Accepts both POSIX '/' and Windows '\\' separators. The returned pointer
* aliases @p path or points to a static "." literal for empty paths.
*/
static inline char *basename(char *path)
{
if (!path || !*path) {
return (char *)".";
}
char *last = path;
for (char *p = path; *p; ++p) {
if (*p == '/' || *p == '\\') {
last = p + 1;
}
}
return *last ? last : (char *)".";
}
/**
* @brief Replace the final path separator with NUL and return the directory.
*
* Accepts both POSIX '/' and Windows '\\' separators. The returned pointer
* aliases @p path or points to a static "." literal when no directory exists.
*/
static inline char *dirname(char *path)
{
if (!path || !*path) {
return (char *)".";
}
char *last = NULL;
for (char *p = path; *p; ++p) {
if (*p == '/' || *p == '\\') {
last = p;
}
}
if (!last) {
return (char *)".";
}
if (last == path) {
last[1] = '\0';
return path;
}
*last = '\0';
return path;
}
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,243 @@
/****************************************************************************
*
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file net/if.h
*
* Windows exposes interface metadata through netioapi/iphlpapi rather than
* POSIX ioctls. This header keeps the public POSIX networking surface
* available: IF_* sizing, interface flags, ifreq/ifconf containers,
* if_nameindex, and the common SIOCGIF* request numbers used by callers as
* compile-time API.
*/
#pragma once
#ifndef _WIN32
# error "net/if.h shim only valid on Windows"
#endif
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <sys/socket.h>
#include <iphlpapi.h>
#include <netioapi.h>
#ifndef IF_NAMESIZE
#define IF_NAMESIZE 256
#endif
#ifndef IFNAMSIZ
#define IFNAMSIZ IF_NAMESIZE
#endif
#ifndef IFHWADDRLEN
#define IFHWADDRLEN 6
#endif
#ifndef MAX_IFINDEX
#define MAX_IFINDEX 256
#endif
/** @brief Hardware mapping payload carried by struct ifreq on POSIX. */
struct ifmap {
unsigned long mem_start;
unsigned long mem_end;
unsigned short base_addr;
unsigned char irq;
unsigned char dma;
unsigned char port;
};
/**
* @brief POSIX interface request container.
*
* POSIX <net/if.h> exposes `struct ifreq` for SIOCGIFNETMASK / SIOCGIFADDR
* ioctls. Windows uses WSAIoctl with SIO_GET_INTERFACE_LIST instead. We
* still need the type to exist so MAVLink signatures parse - the UDP
* broadcast path (query_netmask_addr) is guarded with MAVLINK_UDP and
* stays wired on Windows even though the runtime implementation differs.
*/
struct ifreq {
char ifr_name[IF_NAMESIZE];
union {
struct sockaddr ifr_addr;
struct sockaddr ifr_dstaddr;
struct sockaddr ifr_broadaddr;
struct sockaddr ifr_netmask;
struct sockaddr ifr_hwaddr;
short ifr_flags;
int ifr_ifindex;
int ifr_metric;
int ifr_mtu;
struct ifmap ifr_map;
char ifr_slave[IF_NAMESIZE];
char ifr_newname[IF_NAMESIZE];
char *ifr_data;
} ifr_ifru;
};
#define ifr_addr ifr_ifru.ifr_addr
#define ifr_dstaddr ifr_ifru.ifr_dstaddr
#define ifr_broadaddr ifr_ifru.ifr_broadaddr
#define ifr_netmask ifr_ifru.ifr_netmask
#define ifr_hwaddr ifr_ifru.ifr_hwaddr
#define ifr_flags ifr_ifru.ifr_flags
#define ifr_ifindex ifr_ifru.ifr_ifindex
#define ifr_metric ifr_ifru.ifr_metric
#define ifr_mtu ifr_ifru.ifr_mtu
#define ifr_map ifr_ifru.ifr_map
#define ifr_newname ifr_ifru.ifr_newname
#define ifr_data ifr_ifru.ifr_data
#ifndef IFF_UP
#define IFF_UP 0x1
#endif
#ifndef IFF_DEBUG
#define IFF_DEBUG 0x4
#endif
#ifndef IFF_BROADCAST
#define IFF_BROADCAST 0x2
#endif
#ifndef IFF_LOOPBACK
#define IFF_LOOPBACK 0x8
#endif
#ifndef IFF_POINTOPOINT
#define IFF_POINTOPOINT 0x10
#endif
#ifndef IFF_NOTRAILERS
#define IFF_NOTRAILERS 0x20
#endif
#ifndef IFF_RUNNING
#define IFF_RUNNING 0x40
#endif
#ifndef IFF_NOARP
#define IFF_NOARP 0x80
#endif
#ifndef IFF_PROMISC
#define IFF_PROMISC 0x100
#endif
#ifndef IFF_ALLMULTI
#define IFF_ALLMULTI 0x200
#endif
#ifndef IFF_MASTER
#define IFF_MASTER 0x400
#endif
#ifndef IFF_SLAVE
#define IFF_SLAVE 0x800
#endif
#ifndef IFF_MULTICAST
#define IFF_MULTICAST 0x1000
#endif
#ifndef IFF_PORTSEL
#define IFF_PORTSEL 0x2000
#endif
#ifndef IFF_AUTOMEDIA
#define IFF_AUTOMEDIA 0x4000
#endif
#ifndef IFF_DYNAMIC
#define IFF_DYNAMIC 0x8000
#endif
#define IFF_IS_UP(f) (((f) & IFF_UP) != 0)
#define IFF_IS_RUNNING(f) (((f) & IFF_RUNNING) != 0)
#define IFF_IS_LOOPBACK(f) (((f) & IFF_LOOPBACK) != 0)
#define IFF_IS_POINTOPOINT(f) (((f) & IFF_POINTOPOINT) != 0)
#define IFF_IS_NOARP(f) (((f) & IFF_NOARP) != 0)
#define IFF_IS_MULTICAST(f) (((f) & IFF_MULTICAST) != 0)
#define IFF_IS_BROADCAST(f) (((f) & IFF_BROADCAST) != 0)
#ifndef SIOCGIFCONF
#define SIOCGIFCONF 0x8912
#define SIOCGIFFLAGS 0x8913
#define SIOCSIFFLAGS 0x8914
#define SIOCGIFADDR 0x8915
#define SIOCSIFADDR 0x8916
#define SIOCGIFDSTADDR 0x8917
#define SIOCSIFDSTADDR 0x8918
#define SIOCGIFBRDADDR 0x8919
#define SIOCSIFBRDADDR 0x891A
#define SIOCGIFNETMASK 0x891b
#define SIOCSIFNETMASK 0x891c
#define SIOCGIFMETRIC 0x891d
#define SIOCSIFMETRIC 0x891e
#define SIOCGIFMTU 0x8921
#define SIOCSIFMTU 0x8922
#define SIOCGIFHWADDR 0x8927
#define SIOCGIFINDEX 0x8933
#endif
/**
* @brief POSIX variable-length interface request array for SIOCGIFCONF.
*
* Windows has no direct equivalent (interface enumeration goes through
* GetAdaptersAddresses instead). MAVLink uses ifconf only as a
* type container when walking broadcast addresses - the runtime
* iteration path is stubbed by the shim's ioctl/SIOCGIFCONF handler.
*/
struct ifconf {
int ifc_len;
union {
char *ifc_buf;
struct ifreq *ifc_req;
} ifc_ifcu;
};
#define ifc_buf ifc_ifcu.ifc_buf
#define ifc_req ifc_ifcu.ifc_req
#ifdef __cplusplus
extern "C" {
#endif
/** @brief Interface index/name pair returned by if_nameindex(). */
struct if_nameindex {
unsigned int if_index;
char *if_name;
};
/* `if_nametoindex` and `if_indextoname` are already declared (with
* NET_IFINDEX / PCSTR / PCHAR) by MinGW's <netioapi.h>. Don't redeclare them here - the
* signatures don't match byte-for-byte (NET_IFINDEX vs. unsigned int)
* and GCC flags the conflict as an error. */
/**
* @brief Return a NULL-terminated array of interface index/name pairs.
*
* The implementation queries GetAdaptersAddresses and converts names into the
* POSIX ownership model. Free the returned array with if_freenameindex().
*/
struct if_nameindex *if_nameindex(void);
/** @brief Free an array returned by if_nameindex(). */
void if_freenameindex(struct if_nameindex *ptr);
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,166 @@
/****************************************************************************
*
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file netdb.h
*
* WinSock2 provides getaddrinfo/freeaddrinfo/gethostbyname and the
* struct addrinfo / hostent types, but it ships them through
* <ws2tcpip.h> and <winsock2.h>. Forward to those so the POSIX
* <netdb.h> includes work unchanged, and fill in the legacy BSD pieces
* that Windows omits (`netent`, `hstrerror`, `getnet*`, and the old
* set/end host/service/protocol database walkers).
*/
#pragma once
#ifndef _WIN32
# error "netdb.h shim only valid on Windows"
#endif
#include <stdint.h>
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <winsock2.h>
#include <ws2tcpip.h>
#include <netinet/in.h>
#include <sys/socket.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifndef HOST_NOT_FOUND
#define HOST_NOT_FOUND 11001
#endif
#ifndef TRY_AGAIN
#define TRY_AGAIN 11002
#endif
#ifndef NO_RECOVERY
#define NO_RECOVERY 11003
#endif
#ifndef NO_DATA
#define NO_DATA 11004
#endif
#ifndef NO_ADDRESS
#define NO_ADDRESS NO_DATA
#endif
#ifndef NI_MAXHOST
#define NI_MAXHOST 1025
#endif
#ifndef NI_MAXSERV
#define NI_MAXSERV 32
#endif
#ifndef EAI_SYSTEM
#define EAI_SYSTEM 11
#endif
#ifndef EAI_OVERFLOW
#define EAI_OVERFLOW WSAEFAULT
#endif
#ifndef NI_NUMERICSCOPE
#define NI_NUMERICSCOPE 0x20
#endif
#ifndef IPPORT_RESERVED
#define IPPORT_RESERVED 1024
#endif
#ifndef h_errno
#define h_errno WSAGetLastError()
#endif
/**
* @brief Return human-readable text for legacy resolver errors.
*
* @param err HOST_NOT_FOUND, TRY_AGAIN, NO_RECOVERY, NO_DATA, or a Winsock
* resolver code.
*/
const char *hstrerror(int err);
/** @name Host database compatibility functions
*
* Windows does not expose the old sequential /etc/hosts database API. These
* functions are provided so POSIX-oriented code links; gethostent() returns
* NULL when no synthetic entry is available.
*
* @{
*/
void sethostent(int stay_open);
void endhostent(void);
struct hostent *gethostent(void);
/** @} */
/** @name Network database compatibility functions
*
* The legacy netent API has no Windows equivalent. The implementation returns
* empty results while preserving source and link compatibility.
*
* @{
*/
void setnetent(int stay_open);
void endnetent(void);
struct netent *getnetent(void);
struct netent *getnetbyname(const char *name);
struct netent *getnetbyaddr(uint32_t net, int type);
/** @} */
/** @name Protocol database compatibility functions
*
* Protocol lookup by explicit name/number is handled by Winsock where
* available. Sequential database walking is a no-op compatibility surface.
*
* @{
*/
void setprotoent(int stay_open);
void endprotoent(void);
struct protoent *getprotoent(void);
/** @} */
/** @name Service database compatibility functions
*
* Sequential service database walking is kept as a stub for POSIX source
* compatibility.
*
* @{
*/
void setservent(int stay_open);
void endservent(void);
struct servent *getservent(void);
/** @} */
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,93 @@
/****************************************************************************
*
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file netinet/in.h
*
* Re-export Winsock's IPv4/IPv6 types and normalize the remaining POSIX
* networking surface: fixed-width in_addr_t / in_port_t, POSIX-sized
* INET_ADDRSTRLEN / INET6_ADDRSTRLEN, multicast constants, and a few
* helper aliases that Unix-oriented code expects.
*/
#pragma once
#ifndef _WIN32
# error "netinet/in.h shim only valid on Windows"
#endif
#include <stdint.h>
#include <sys/socket.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#ifndef INADDR_NONE
#define INADDR_NONE ((in_addr_t)0xffffffffUL)
#endif
#ifndef IPPROTO_UDP
# define IPPROTO_UDP 17
#endif
#ifndef IPPROTO_TCP
# define IPPROTO_TCP 6
#endif
#ifndef _PX4_IN_ADDR_T_DEFINED_SHIM
#define _PX4_IN_ADDR_T_DEFINED_SHIM
/** @brief IPv4 address integer type used by POSIX networking APIs. */
typedef uint32_t in_addr_t;
#endif
#ifndef _PX4_IN_PORT_T_DEFINED_SHIM
#define _PX4_IN_PORT_T_DEFINED_SHIM
/** @brief TCP/UDP port integer type used by POSIX networking APIs. */
typedef uint16_t in_port_t;
#endif
#ifdef INET_ADDRSTRLEN
#undef INET_ADDRSTRLEN
#endif
#define INET_ADDRSTRLEN 16
#ifdef INET6_ADDRSTRLEN
#undef INET6_ADDRSTRLEN
#endif
#define INET6_ADDRSTRLEN 46
#ifndef MCAST_INCLUDE
#define MCAST_INCLUDE 1
#endif
#ifndef MCAST_EXCLUDE
#define MCAST_EXCLUDE 0
#endif
#ifndef IN6_ARE_ADDR_EQUAL
#define IN6_ARE_ADDR_EQUAL(a, b) IN6_ADDR_EQUAL((a), (b))
#endif
@@ -0,0 +1,72 @@
/****************************************************************************
*
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file netinet/tcp.h
*
* Export the standard TCP-level option names. Where Winsock has no symbolic
* equivalent, keep the POSIX macro available as a compile-time compatibility
* constant; runtime support still depends on the underlying Windows stack.
*/
#pragma once
#ifndef _WIN32
# error "netinet/tcp.h shim only valid on Windows"
#endif
#include <netinet/in.h>
#include <winsock2.h>
#include <ws2tcpip.h>
/* winsock already defines TCP_NODELAY. */
#ifndef SOL_TCP
#define SOL_TCP IPPROTO_TCP
#endif
#ifndef TCP_KEEPIDLE
#ifdef TCP_KEEPALIVE
#define TCP_KEEPIDLE TCP_KEEPALIVE
#else
#define TCP_KEEPIDLE 3
#endif
#endif
#ifndef TCP_KEEPINTVL
#define TCP_KEEPINTVL 17
#endif
#ifndef TCP_KEEPCNT
#define TCP_KEEPCNT 16
#endif
#ifndef TCP_MAXSEG
#define TCP_MAXSEG 4
#endif
#ifndef TCP_USER_TIMEOUT
#define TCP_USER_TIMEOUT 18
#endif
@@ -0,0 +1,49 @@
/****************************************************************************
*
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file netinet/udp.h
*
* POSIX mainly uses this header for the UDP protocol-level socket constant.
* Winsock exposes UDP through IPPROTO_UDP, so re-export that shape here.
*/
#pragma once
#ifndef _WIN32
# error "netinet/udp.h shim only valid on Windows"
#endif
#include <netinet/in.h>
#ifndef SOL_UDP
#define SOL_UDP IPPROTO_UDP
#endif
@@ -0,0 +1,87 @@
/****************************************************************************
*
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file poll.h
*
* Maps POSIX poll() onto Win32 WSAPoll(). WSAPoll has the same struct
* layout and event flags as POSIX poll; it has been available since
* Vista but only works on sockets, which is exactly how PX4 uses it
* (px4_daemon socket pair, muorb sockets, mavlink).
*/
#pragma once
#include <winsock2.h>
#ifdef __cplusplus
extern "C" {
#endif
/* winsock2 already defines pollfd / WSAPOLLFD and the event bits when
* _WIN32_WINNT >= 0x0600 (Vista). Re-export as the POSIX-style names. */
#ifndef POLLRDNORM
#define POLLRDNORM POLLIN
#endif
#ifndef POLLRDBAND
#define POLLRDBAND 0x0080
#endif
#ifndef POLLWRNORM
#define POLLWRNORM POLLOUT
#endif
#ifndef POLLWRBAND
#define POLLWRBAND 0x0100
#endif
#ifndef POLLMSG
#define POLLMSG 0x0400
#endif
#ifndef POLLREMOVE
#define POLLREMOVE 0x1000
#endif
typedef struct pollfd POLLFD; /* alias for readability */
typedef unsigned long nfds_t;
/**
* @brief Poll socket descriptors using WSAPoll().
*
* @return Number of ready descriptors, 0 on timeout, or SOCKET_ERROR.
*/
static inline int poll(struct pollfd *fds, nfds_t nfds, int timeout)
{
return WSAPoll(fds, (ULONG)nfds, timeout);
}
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,246 @@
/****************************************************************************
*
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file pthread.h
*
* MinGW-w64 links winpthreads which ships a full <pthread.h>, but it
* omits a handful of POSIX macros that PX4 uses (PTHREAD_STACK_MIN). We
* forward to the real header via #include_next and add the missing
* pieces with values consistent with how Windows actually behaves
* (allocation granularity = 64 KiB, pthread_attr_setstacksize rounds
* up to it anyway).
*/
#pragma once
#if defined(_MSC_VER) && !defined(__clang__)
#include <windows.h>
#include <time.h>
#include <stdint.h>
#include <sched.h>
#ifdef __cplusplus
extern "C" {
#endif
/** @brief Thread handle stored as an integer-sized Windows HANDLE value. */
typedef uintptr_t pthread_t;
/** @brief Thread-local storage key backed by TlsAlloc/TlsFree. */
typedef DWORD pthread_key_t;
/**
* @brief Thread creation attributes understood by the MSVC pthread shim.
*
* Scheduling fields are stored for POSIX API round-tripping; Windows thread
* creation only consumes detach state and stack size.
*/
typedef struct pthread_attr_t {
void *stack_addr;
size_t stack_size;
int detach_state;
int sched_policy;
int inherit_sched;
int scope;
struct sched_param sched;
} pthread_attr_t;
/** @brief Mutex attribute object; currently carries only the mutex type. */
typedef struct pthread_mutexattr_t {
int type;
} pthread_mutexattr_t;
/** @brief Condition-variable attribute object; stores the requested clock. */
typedef struct pthread_condattr_t {
int clock_id;
} pthread_condattr_t;
/**
* @brief Mutex object backed by a lazily initialized CRITICAL_SECTION.
*
* The INIT_ONCE field lets static PTHREAD_MUTEX_INITIALIZER instances be
* initialized on first lock without requiring a constructor.
*/
typedef struct pthread_mutex_t {
INIT_ONCE once;
CRITICAL_SECTION critical_section;
int type;
} pthread_mutex_t;
/** @brief Condition variable object backed directly by CONDITION_VARIABLE. */
typedef CONDITION_VARIABLE pthread_cond_t;
/** @brief One-time initialization guard backed by INIT_ONCE. */
typedef INIT_ONCE pthread_once_t;
#define PTHREAD_MUTEX_INITIALIZER { INIT_ONCE_STATIC_INIT, { 0 }, 0 }
#define PTHREAD_COND_INITIALIZER CONDITION_VARIABLE_INIT
#define PTHREAD_ONCE_INIT INIT_ONCE_STATIC_INIT
#define PTHREAD_MUTEX_NORMAL 0
#define PTHREAD_MUTEX_RECURSIVE 1
#define PTHREAD_PROCESS_PRIVATE 0
#define PTHREAD_CREATE_JOINABLE 0
#define PTHREAD_CREATE_DETACHED 1
#define PTHREAD_INHERIT_SCHED 0
#define PTHREAD_EXPLICIT_SCHED 1
#define PTHREAD_SCOPE_SYSTEM 0
#define PTHREAD_SCOPE_PROCESS 1
/** @name Thread attribute functions
*
* Store POSIX pthread attributes for later pthread_create() calls. Unsupported
* scheduling/scope attributes are retained for round-trip queries and ignored
* by Windows thread creation.
*
* @{
*/
int pthread_attr_init(pthread_attr_t *attr);
int pthread_attr_destroy(pthread_attr_t *attr);
int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stack_size);
int pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stack_size);
int pthread_attr_setstack(pthread_attr_t *attr, void *stack_addr, size_t stack_size);
int pthread_attr_getstack(const pthread_attr_t *attr, void **stack_addr, size_t *stack_size);
int pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param);
int pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param);
int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy);
int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);
int pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inheritsched);
int pthread_attr_setinheritsched(pthread_attr_t *attr, int inheritsched);
int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
int pthread_attr_getscope(const pthread_attr_t *attr, int *scope);
int pthread_attr_setscope(pthread_attr_t *attr, int scope);
/** @} */
/** @name Mutex functions
*
* Implement POSIX mutex operations on top of CRITICAL_SECTION. Recursive
* mutexes are accepted through pthread_mutexattr_settype().
*
* @{
*/
int pthread_mutexattr_init(pthread_mutexattr_t *attr);
int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);
int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type);
int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type);
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
/** @} */
/** @name Condition-variable functions
*
* Implement pthread condition variables with SleepConditionVariableCS and
* WakeConditionVariable/WakeAllConditionVariable.
*
* @{
*/
int pthread_condattr_init(pthread_condattr_t *attr);
int pthread_condattr_destroy(pthread_condattr_t *attr);
int pthread_condattr_setclock(pthread_condattr_t *attr, clockid_t clock_id);
int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);
int pthread_cond_destroy(pthread_cond_t *cond);
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime);
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);
/** @} */
/** @name Thread lifecycle functions
*
* Wrap CreateThread/WaitForSingleObject/CloseHandle with pthread-compatible
* ownership and return codes.
*
* @{
*/
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);
int pthread_join(pthread_t thread, void **value_ptr);
int pthread_detach(pthread_t thread);
void pthread_exit(void *value_ptr);
pthread_t pthread_self(void);
int pthread_equal(pthread_t t1, pthread_t t2);
int pthread_cancel(pthread_t thread);
int pthread_kill(pthread_t thread, int sig);
/** @} */
/** @name Thread-local storage functions
*
* Back POSIX pthread keys with the Windows TLS API.
*
* @{
*/
int pthread_key_create(pthread_key_t *key, void (*destructor)(void *));
int pthread_key_delete(pthread_key_t key);
int pthread_setspecific(pthread_key_t key, const void *value);
void *pthread_getspecific(pthread_key_t key);
/** @} */
/** @brief Run an initialization routine exactly once. */
int pthread_once(pthread_once_t *once_control, void (*init_routine)(void));
/**
* @brief Name another thread for debuggers.
*
* @param thread Thread returned by pthread_create() or pthread_self().
* @param name UTF-8 thread name.
*/
int px4_pthread_setname_np(pthread_t thread, const char *name);
/**
* @brief Name the current thread for debuggers.
*
* pthread_setname_np has one-argument and two-argument variants across POSIX
* platforms, so the macro below dispatches to this helper when only a name is
* supplied.
*/
int px4_pthread_setname_current_np(const char *name);
/** @brief Read a thread name previously set through the shim when available. */
int pthread_getname_np(pthread_t thread, char *name, size_t len);
#define PX4_PTHREAD_SETNAME_SELECT(_1, _2, NAME, ...) NAME
#define pthread_setname_np(...) PX4_PTHREAD_SETNAME_SELECT(__VA_ARGS__, px4_pthread_setname_np, px4_pthread_setname_current_np)(__VA_ARGS__)
#ifdef __cplusplus
}
#endif
#else
#include_next <pthread.h>
#endif
#ifndef PTHREAD_STACK_MIN
#define PTHREAD_STACK_MIN 16384
#endif
@@ -0,0 +1,95 @@
/****************************************************************************
*
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file pwd.h
*
* Windows has no /etc/passwd. SITL consumers only ever want the current
* user's home directory or name - we synthesise a passwd entry from
* %USERPROFILE% / GetUserName to keep them building and (mostly) working.
*/
#pragma once
#include <stddef.h>
#include <sys/types.h>
/* MinGW's sys/types.h does not define uid_t/gid_t. */
#ifndef _PX4_UID_T_DEFINED_SHIM
#define _PX4_UID_T_DEFINED_SHIM
typedef unsigned int uid_t;
typedef unsigned int gid_t;
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief POSIX passwd entry synthesized from the current Windows user.
*/
struct passwd {
char *pw_name;
char *pw_passwd;
uid_t pw_uid;
gid_t pw_gid;
char *pw_gecos;
char *pw_dir;
char *pw_shell;
};
/** @brief Return a static passwd entry for the requested UID when available. */
struct passwd *getpwuid(uid_t uid);
/** @brief Return a static passwd entry for the requested user name. */
struct passwd *getpwnam(const char *name);
/**
* @brief Reentrant UID lookup.
*
* @return 0 on success or not found; @p result is NULL when no entry matches.
* Returns an errno value when @p buf is too small or arguments are
* invalid.
*/
int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf, size_t buflen, struct passwd **result);
/**
* @brief Reentrant name lookup.
*
* @return 0 on success or not found; @p result is NULL when no entry matches.
* Returns an errno value when @p buf is too small or arguments are
* invalid.
*/
int getpwnam_r(const char *name, struct passwd *pwd, char *buf, size_t buflen, struct passwd **result);
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,90 @@
/****************************************************************************
*
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file sched.h
*
* POSIX scheduler surface for native Windows builds.
*/
#pragma once
#if defined(_MSC_VER) && !defined(__clang__)
#include <windows.h>
#ifndef SCHED_OTHER
#define SCHED_OTHER 0
#endif
#ifndef SCHED_FIFO
#define SCHED_FIFO 1
#endif
#ifndef SCHED_RR
#define SCHED_RR 2
#endif
struct sched_param {
int sched_priority;
};
#ifdef __cplusplus
extern "C" {
#endif
/** @brief Return the highest priority value accepted by the shim. */
static inline int sched_get_priority_max(int policy)
{
(void)policy;
return 15;
}
/** @brief Return the lowest priority value accepted by the shim. */
static inline int sched_get_priority_min(int policy)
{
(void)policy;
return -15;
}
/** @brief Yield the current Windows thread's remaining time slice. */
static inline int sched_yield(void)
{
Sleep(0);
return 0;
}
#ifdef __cplusplus
}
#endif
#else
#include_next <sched.h>
#endif
@@ -0,0 +1,50 @@
/****************************************************************************
*
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file semaphore.h
*
* Native Windows placeholder for POSIX semaphore headers. PX4 POSIX builds
* use px4_sem_t on Windows, so sem_t only needs to exist for code that
* includes <semaphore.h> without directly using POSIX sem_* calls.
*/
#pragma once
#if defined(_MSC_VER) && !defined(__clang__)
/** @brief Placeholder POSIX semaphore type for code that only needs the name. */
typedef void *sem_t;
#else
#include_next <semaphore.h>
#endif
@@ -0,0 +1,176 @@
/****************************************************************************
*
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file signal.h
*
* Re-exports the MinGW signal.h and adds the POSIX signal numbers that PX4
* code references but MinGW does not define (SIGCONT, SIGUSR1, etc.).
* These values never reach the Win32 kernel - the PX4 runtime intercepts
* them in px4_task_kill() and treats them as thread wake-up hints
* (implemented via pthread_kill / no-op, since winpthreads can't signal
* a thread with an arbitrary value).
*/
#pragma once
#if defined(_MSC_VER) && !defined(__clang__)
#if defined(__has_include)
# if __has_include(<../ucrt/signal.h>)
# include <../ucrt/signal.h>
# endif
#endif
/** @brief Function-pointer type used by the MSVC signal() declaration. */
typedef void (*__px4_signal_handler_t)(int);
#ifndef SIG_ERR
#define SIG_ERR ((__px4_signal_handler_t)-1)
#endif
#ifndef SIG_DFL
#define SIG_DFL ((__px4_signal_handler_t)0)
#endif
#ifndef SIG_IGN
#define SIG_IGN ((__px4_signal_handler_t)1)
#endif
#ifndef SIGINT
#define SIGINT 2
#endif
#ifndef SIGILL
#define SIGILL 4
#endif
#ifndef SIGABRT
#define SIGABRT 22
#endif
#ifndef SIGFPE
#define SIGFPE 8
#endif
#ifndef SIGSEGV
#define SIGSEGV 11
#endif
#ifndef SIGTERM
#define SIGTERM 15
#endif
#ifdef __cplusplus
extern "C" {
#endif
/** @brief Register a C runtime signal handler. */
__px4_signal_handler_t signal(int sig, __px4_signal_handler_t func);
/** @brief Raise a C runtime signal in the current process. */
int raise(int sig);
#ifdef __cplusplus
}
#endif
#else
#include_next <signal.h>
#endif
#ifndef SIGHUP
#define SIGHUP 1
#endif
#ifndef SIGQUIT
#define SIGQUIT 3
#endif
#ifndef SIGKILL
#define SIGKILL 9
#endif
#ifndef SIGUSR1
#define SIGUSR1 10
#endif
#ifndef SIGUSR2
#define SIGUSR2 12
#endif
#ifndef SIGPIPE
#define SIGPIPE 13
#endif
#ifndef SIGBUS
#define SIGBUS 7
#endif
#ifndef SIGTRAP
#define SIGTRAP 5
#endif
#ifndef SIGALRM
#define SIGALRM 14
#endif
#ifndef SIGCHLD
#define SIGCHLD 17
#endif
#ifndef SIGCONT
#define SIGCONT 18
#endif
#ifndef SIGSTOP
#define SIGSTOP 19
#endif
#ifndef SIGTSTP
#define SIGTSTP 20
#endif
#ifndef SIGTTIN
#define SIGTTIN 21
#endif
#ifndef SIGTTOU
#define SIGTTOU 22
#endif
#ifndef SIGWINCH
#define SIGWINCH 28
#endif
#ifndef SIGPOLL
#define SIGPOLL 29
#endif
#ifndef SIG_BLOCK
#define SIG_BLOCK 0
#endif
#ifndef SIG_UNBLOCK
#define SIG_UNBLOCK 1
#endif
#ifndef SIG_SETMASK
#define SIG_SETMASK 2
#endif
#ifndef SA_RESTART
#define SA_RESTART 0x10000000
#endif
#ifndef SA_NOCLDSTOP
#define SA_NOCLDSTOP 0x00000001
#endif
#ifndef SA_NOCLDWAIT
#define SA_NOCLDWAIT 0x00000002
#endif
#ifndef SA_NODEFER
#define SA_NODEFER 0x40000000
#endif
#ifndef SA_RESETHAND
#define SA_RESETHAND 0x80000000
#endif
#ifndef SA_SIGINFO
#define SA_SIGINFO 4
#endif
#ifndef NSIG
#define NSIG 32
#endif
@@ -0,0 +1,67 @@
/****************************************************************************
*
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file string.h
*
* MSVC CRT names a few POSIX string helpers with leading underscores.
*/
#pragma once
#if defined(_MSC_VER) && !defined(__clang__)
#if defined(__has_include)
# if __has_include(<../ucrt/string.h>)
# include <../ucrt/string.h>
# else
# include <string.h>
# endif
#else
#include <string.h>
#endif
#include <stdlib.h>
#ifndef strdup
#define strdup _strdup
#endif
#ifndef strcasecmp
#define strcasecmp _stricmp
#endif
#ifndef strncasecmp
#define strncasecmp _strnicmp
#endif
#ifndef bzero
#define bzero(ptr, len) memset((ptr), 0, (len))
#endif
#else
#include_next <string.h>
#endif
@@ -0,0 +1,41 @@
/****************************************************************************
*
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file strings.h
*
* BSD/POSIX string helper names for Windows builds.
*/
#pragma once
#include <string.h>
@@ -0,0 +1,62 @@
/****************************************************************************
*
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file sys/file.h
*
* PX4's main.cpp uses flock(fd, LOCK_EX|LOCK_NB) on a lock file
* (/tmp/px4_lock) to detect and reject a second running instance.
* On Windows we translate this to LockFileEx on the file's HANDLE,
* backed by _get_osfhandle(fd).
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#define LOCK_SH 1
#define LOCK_EX 2
#define LOCK_NB 4
#define LOCK_UN 8
/**
* @brief Apply or release an advisory lock on a CRT file descriptor.
*
* Used by PX4's singleton lock. The Windows implementation maps exclusive
* locks to LockFileEx on the descriptor's underlying HANDLE.
*/
int flock(int fd, int operation);
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,118 @@
/****************************************************************************
*
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file sys/ioctl.h
*
* SITL does not actually drive ioctl'd character devices on Windows -
* there is no /dev/tty or /dev/mem. Callers include <sys/ioctl.h>
* for FIONREAD/FIONBIO/TIOCM* constants. We expose those symbols,
* route FIONREAD/FIONBIO through winsock's ioctlsocket (which uses the
* same FIONREAD/FIONBIO values), and return -ENOSYS for anything else.
*/
#pragma once
#include <sys/types.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifndef FIONREAD
# define FIONREAD 0x4004667F
#endif
#ifndef FIONBIO
# define FIONBIO 0x8004667E
#endif
#ifndef TIOCINQ
# define TIOCINQ FIONREAD
#endif
#ifndef TIOCOUTQ
# define TIOCOUTQ 0x5411
#endif
#ifndef FIOCLEX
# define FIOCLEX 0x5451
#endif
#ifndef FIONCLEX
# define FIONCLEX 0x5450
#endif
#ifndef TIOCEXCL
# define TIOCEXCL 0x540C
#endif
#ifndef TIOCNXCL
# define TIOCNXCL 0x540D
#endif
#ifndef TIOCSCTTY
# define TIOCSCTTY 0x540E
#endif
#ifndef TIOCMGET
# define TIOCMGET 0x5415
#endif
#ifndef TIOCMSET
# define TIOCMSET 0x5418
#endif
#ifndef TIOCM_DTR
# define TIOCM_DTR 0x002
#endif
#ifndef TIOCM_RTS
# define TIOCM_RTS 0x004
#endif
#ifndef TIOCSBRK
# define TIOCSBRK 0x5427
#endif
#ifndef TIOCCBRK
# define TIOCCBRK 0x5428
#endif
#ifndef TCGETS
# define TCGETS 0x5401
#endif
#ifndef TCSETS
# define TCSETS 0x5402
#endif
#ifndef TCSETSW
# define TCSETSW 0x5403
#endif
#ifndef TCSETSF
# define TCSETSF 0x5404
#endif
/**
* @brief POSIX ioctl() compatibility subset for sockets and terminal constants.
*
* FIONREAD/FIONBIO are forwarded to ioctlsocket(). Unsupported requests fail
* with ENOSYS so callers can follow their existing POSIX fallback path.
*/
int ioctl(int fd, unsigned long request, ...);
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,140 @@
/****************************************************************************
*
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file sys/mman.h
*
* Covers the mmap surface SITL uses: anonymous memory for parameter
* backing stores / shared memory, and file-backed memory for logs and
* dataman. Backed by VirtualAlloc (anonymous) and CreateFileMapping +
* MapViewOfFile (file-backed). mlock/mlockall are no-ops - Windows
* has VirtualLock but requires the SeLockMemoryPrivilege which SITL
* does not need.
*/
#pragma once
#include <sys/types.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
#define PROT_NONE 0x0
#define PROT_READ 0x1
#define PROT_WRITE 0x2
#define PROT_EXEC 0x4
#define MAP_SHARED 0x01
#define MAP_PRIVATE 0x02
#define MAP_FIXED 0x10
#define MAP_ANON 0x20
#define MAP_ANONYMOUS MAP_ANON
#define MAP_NORESERVE 0x4000
#define MAP_POPULATE 0x8000
#define MAP_LOCKED 0x2000
#define MAP_FAILED ((void *) -1)
#define MS_ASYNC 1
#define MS_SYNC 4
#define MS_INVALIDATE 2
#define MCL_CURRENT 1
#define MCL_FUTURE 2
#define MADV_NORMAL 0
#define MADV_RANDOM 1
#define MADV_SEQUENTIAL 2
#define MADV_WILLNEED 3
#define MADV_DONTNEED 4
#define POSIX_MADV_NORMAL MADV_NORMAL
#define POSIX_MADV_RANDOM MADV_RANDOM
#define POSIX_MADV_SEQUENTIAL MADV_SEQUENTIAL
#define POSIX_MADV_WILLNEED MADV_WILLNEED
#define POSIX_MADV_DONTNEED MADV_DONTNEED
/**
* @brief Map anonymous or file-backed memory into the process.
*
* @param addr Requested address. MAP_FIXED is rejected because the Windows
* backend does not support safely replacing existing mappings.
* @param length Mapping length in bytes.
* @param prot POSIX PROT_* protection bits.
* @param flags POSIX MAP_* flags. MAP_ANONYMOUS uses VirtualAlloc; file-backed
* mappings use CreateFileMapping/MapViewOfFile.
* @param fd CRT file descriptor for file-backed mappings, or -1 for anonymous.
* @param offset File offset for file-backed mappings.
* @return Mapped address, or MAP_FAILED with errno set.
*/
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
/** @brief Unmap a region returned by mmap(). */
int munmap(void *addr, size_t length);
/** @brief Flush a mapped file range when the mapping is file-backed. */
int msync(void *addr, size_t length, int flags);
/** @brief Change page protection for an existing mapping. */
int mprotect(void *addr, size_t length, int prot);
/** @brief Accept POSIX memory-lock calls; currently a no-op on Windows. */
int mlock(const void *addr, size_t length);
/** @brief Accept POSIX memory-unlock calls; currently a no-op on Windows. */
int munlock(const void *addr, size_t length);
/** @brief Accept process-wide memory-lock calls; currently a no-op. */
int mlockall(int flags);
/** @brief Accept process-wide memory-unlock calls; currently a no-op. */
int munlockall(void);
/**
* @brief Accept POSIX memory-advice calls.
*
* Windows has PrefetchVirtualMemory on newer releases, but PX4 does not depend
* on advisory paging behavior. Returning success matches the permissive POSIX
* interpretation for unsupported advice.
*/
static inline int madvise(void *addr, size_t length, int advice)
{
(void)addr;
(void)length;
(void)advice;
return 0;
}
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,46 @@
/****************************************************************************
*
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file sys/select.h
*
* WinSock provides fd_set/select/timeval; expose it at the POSIX path.
*/
#pragma once
#if defined(_MSC_VER) && !defined(__clang__)
#include <sys/socket.h>
#include <sys/time.h>
#else
#include_next <sys/select.h>
#endif
@@ -0,0 +1,266 @@
/****************************************************************************
*
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file sys/socket.h
*
* MinGW ships winsock2.h; POSIX code expects <sys/socket.h>. Pull in
* winsock2/ws2tcpip and expose the POSIX-style socket typedefs,
* ancillary-message structs, MSG_* flags, sendmsg/recvmsg, and a
* local socketpair() helper.
* A matching <netinet/in.h> / <arpa/inet.h> sit next to this file and
* simply re-include us.
*/
#pragma once
#include <stddef.h>
#include <stdint.h>
#include <sys/types.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <mswsock.h>
#ifdef __cplusplus
extern "C" {
#endif
/* POSIX names mapped onto winsock types. */
typedef int socklen_t_compat_unused_; /* placeholder, ws2tcpip provides socklen_t */
typedef SSIZE_T ssize_t_socket_unused_;
#ifndef _PX4_SA_FAMILY_T_DEFINED
#define _PX4_SA_FAMILY_T_DEFINED
typedef ADDRESS_FAMILY sa_family_t;
#endif
#ifndef AF_LOCAL
#define AF_LOCAL AF_UNIX
#endif
#ifndef PF_LOCAL
#define PF_LOCAL PF_UNIX
#endif
#ifndef _PX4_IOVEC_DEFINED
#define _PX4_IOVEC_DEFINED
/** @brief Scatter/gather buffer descriptor used by sendmsg()/recvmsg(). */
struct iovec {
void *iov_base;
size_t iov_len;
};
#endif
#ifndef _PX4_MSGHDR_DEFINED
#define _PX4_MSGHDR_DEFINED
/**
* @brief POSIX message header for vectored socket I/O.
*
* The Windows backend supports payload iovecs and the ancillary fields needed
* for source compatibility. Unsupported control-message types are ignored by
* the implementation.
*/
struct msghdr {
void *msg_name;
socklen_t msg_namelen;
struct iovec *msg_iov;
int msg_iovlen;
void *msg_control;
size_t msg_controllen;
int msg_flags;
};
/** @brief Ancillary data header compatible with POSIX CMSG_* helpers. */
struct cmsghdr {
size_t cmsg_len;
int cmsg_level;
int cmsg_type;
};
#ifndef _PX4_UCRED_DEFINED
#define _PX4_UCRED_DEFINED
/** @brief Credential payload shape used by SCM_CREDENTIALS call sites. */
struct ucred {
int pid;
unsigned int uid;
unsigned int gid;
};
#endif
#endif
#ifndef CMSG_ALIGN
#define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
#endif
#ifndef CMSG_SPACE
#define CMSG_SPACE(len) (CMSG_ALIGN(sizeof(struct cmsghdr)) + CMSG_ALIGN(len))
#endif
#ifndef CMSG_LEN
#define CMSG_LEN(len) (CMSG_ALIGN(sizeof(struct cmsghdr)) + (len))
#endif
#ifndef CMSG_DATA
#define CMSG_DATA(cmsg) ((unsigned char *)(cmsg) + CMSG_ALIGN(sizeof(struct cmsghdr)))
#endif
#ifndef CMSG_FIRSTHDR
#define CMSG_FIRSTHDR(msg) ((msg)->msg_controllen >= sizeof(struct cmsghdr) ? (struct cmsghdr *)(msg)->msg_control : (struct cmsghdr *)0)
#endif
#ifndef CMSG_NXTHDR
#define CMSG_NXTHDR(msg, cmsg) \
(((uintptr_t)(CMSG_DATA(cmsg)) + CMSG_ALIGN((cmsg)->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr))) + CMSG_ALIGN(sizeof(struct cmsghdr)) > \
(uintptr_t)(msg)->msg_control + (msg)->msg_controllen) ? \
(struct cmsghdr *)0 : \
(struct cmsghdr *)((unsigned char *)(cmsg) + CMSG_ALIGN((cmsg)->cmsg_len)))
#endif
#ifndef SCM_RIGHTS
#define SCM_RIGHTS 0x01
#endif
#ifndef SCM_CREDENTIALS
#define SCM_CREDENTIALS 0x02
#endif
/* POSIX send/recv flags. winsock covers MSG_OOB/PEEK/DONTROUTE; the rest
* we map to 0 so callers still compile. */
#ifndef MSG_TRUNC
# define MSG_TRUNC 0
#endif
#ifndef MSG_EOR
# define MSG_EOR 0
#endif
#ifndef MSG_CTRUNC
# define MSG_CTRUNC 0
#endif
#ifndef MSG_CONFIRM
# define MSG_CONFIRM 0
#endif
#ifndef MSG_ERRQUEUE
# define MSG_ERRQUEUE 0
#endif
#ifndef MSG_WAITALL
# define MSG_WAITALL 0
#endif
#ifndef MSG_WAITFORONE
# define MSG_WAITFORONE 0
#endif
#ifndef MSG_DONTWAIT
# define MSG_DONTWAIT 0
#endif
#ifndef MSG_MORE
# define MSG_MORE 0
#endif
#ifndef MSG_NOSIGNAL
# define MSG_NOSIGNAL 0
#endif
#ifndef MSG_CMSG_CLOEXEC
# define MSG_CMSG_CLOEXEC 0
#endif
#ifndef SOCK_CLOEXEC
# define SOCK_CLOEXEC 0
#endif
#ifndef SOCK_NONBLOCK
# define SOCK_NONBLOCK 0
#endif
/* Shutdown how values - winsock uses SD_RECEIVE/SD_SEND/SD_BOTH;
* POSIX code expects SHUT_*. */
#ifndef SHUT_RD
# define SHUT_RD SD_RECEIVE
#endif
#ifndef SHUT_WR
# define SHUT_WR SD_SEND
#endif
#ifndef SHUT_RDWR
# define SHUT_RDWR SD_BOTH
#endif
/**
* @brief Send a POSIX msghdr over a Winsock socket.
*
* @return Number of bytes sent, or -1 with errno set from WSAGetLastError().
*/
ssize_t sendmsg(int socket, const struct msghdr *message, int flags);
/**
* @brief Receive data into a POSIX msghdr from a Winsock socket.
*
* @return Number of bytes received, or -1 with errno set from WSAGetLastError().
*/
ssize_t recvmsg(int socket, struct msghdr *message, int flags);
/**
* @brief Create a connected socket pair for PX4 daemon/shell IPC.
*
* Windows AF_UNIX support is not present on every target we care about, so the
* implementation may fall back to a loopback TCP pair while preserving POSIX
* socketpair() behavior for the caller.
*/
int socketpair(int domain, int type, int protocol, int socket_vector[2]);
#if defined(_MSC_VER) && !defined(__clang__) && !defined(PX4_WINDOWS_NO_SOCKET_MACROS)
/**
* @name MSVC socket wrappers
*
* MSVC does not expose POSIX-like int socket descriptors. These wrappers keep
* PX4 source code using socket(), bind(), send(), etc. while centralizing
* Winsock startup and errno translation in the Windows backend.
*
* @{
*/
SOCKET WSAAPI px4_windows_socket(int af, int type, int protocol);
int WSAAPI px4_windows_bind(SOCKET s, const struct sockaddr *name, int namelen);
int WSAAPI px4_windows_listen(SOCKET s, int backlog);
SOCKET WSAAPI px4_windows_accept(SOCKET s, struct sockaddr *addr, int *addrlen);
int WSAAPI px4_windows_connect(SOCKET s, const struct sockaddr *name, int namelen);
int WSAAPI px4_windows_setsockopt(SOCKET s, int level, int optname, const char *optval, int optlen);
int WSAAPI px4_windows_shutdown(SOCKET s, int how);
int WSAAPI px4_windows_recv(SOCKET s, char *buf, int len, int flags);
int WSAAPI px4_windows_send(SOCKET s, const char *buf, int len, int flags);
int WSAAPI px4_windows_recvfrom(SOCKET s, char *buf, int len, int flags, struct sockaddr *from, int *fromlen);
int WSAAPI px4_windows_sendto(SOCKET s, const char *buf, int len, int flags, const struct sockaddr *to, int tolen);
char *px4_windows_strerror(int e);
/** @} */
#define socket(...) px4_windows_socket(__VA_ARGS__)
#define bind(...) px4_windows_bind(__VA_ARGS__)
#define listen(...) px4_windows_listen(__VA_ARGS__)
#define accept(...) px4_windows_accept(__VA_ARGS__)
#define connect(...) px4_windows_connect(__VA_ARGS__)
#define setsockopt(...) px4_windows_setsockopt(__VA_ARGS__)
#define shutdown(...) px4_windows_shutdown(__VA_ARGS__)
#define recv(...) px4_windows_recv(__VA_ARGS__)
#define send(...) px4_windows_send(__VA_ARGS__)
#define recvfrom(...) px4_windows_recvfrom(__VA_ARGS__)
#define sendto(...) px4_windows_sendto(__VA_ARGS__)
#define strerror(...) px4_windows_strerror(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,53 @@
/****************************************************************************
*
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file sys/socketopt_compat.h
*
* Small compatibility helpers for call sites that want POSIX-shaped
* setsockopt arguments. Kept here so it can be included on demand.
*/
#pragma once
#include <winsock2.h>
/**
* @brief Set SO_REUSEADDR with an int argument like POSIX call sites expect.
*
* Winsock's setsockopt() takes a char pointer. Keeping this helper avoids
* sprinkling casts through shared networking code.
*/
static inline int px4_set_socket_reuseaddr(int fd, int enable)
{
return setsockopt((SOCKET)fd, SOL_SOCKET, SO_REUSEADDR,
(const char *)&enable, sizeof(enable));
}
@@ -0,0 +1,193 @@
/****************************************************************************
*
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file sys/stat.h
*
* MinGW's sys/stat.h provides POSIX's 1-argument `mkdir(path)` (forwarded
* to _mkdir). PX4 - along with almost every POSIX codebase - uses the
* 2-argument form `mkdir(path, mode)`. Wrap the real call in an inline
* that ignores the mode bits (Windows ACLs don't map to POSIX permission
* bits anyway).
*/
#pragma once
#if defined(_MSC_VER) && !defined(__clang__)
#if defined(__has_include)
# if __has_include(<../ucrt/sys/stat.h>)
# include <../ucrt/sys/stat.h>
# endif
#endif
#include <sys/types.h>
#else
#include_next <sys/stat.h>
#endif
#include <direct.h>
#include <sys/types.h>
#ifndef _PX4_MKDIR_SHIM_DEFINED
#define _PX4_MKDIR_SHIM_DEFINED
/* Replace any existing mkdir macro/prototype with a 2-arg form that
* ignores the mode argument and falls back to _mkdir internally. */
#ifdef mkdir
#undef mkdir
#endif
#ifdef __cplusplus
extern "C" {
#endif
/** @brief Two-argument POSIX mkdir() wrapper around Windows _mkdir(). */
static inline int px4_mkdir_shim(const char *path, mode_t mode)
{
(void)mode;
return _mkdir(path);
}
#ifdef __cplusplus
}
#endif
#define mkdir(path, mode) px4_mkdir_shim((path), (mode))
#endif /* _PX4_MKDIR_SHIM_DEFINED */
/* POSIX permission bits that Windows's sys/stat.h partially ships. Fill
* in the rest with matching numeric values so code that OR's them
* compiles. */
#ifndef S_IRWXU
#define S_IRWXU 0700
#endif
#ifndef S_IFMT
#define S_IFMT 0170000
#endif
#ifndef S_IFIFO
#define S_IFIFO 0010000
#endif
#ifndef S_IFCHR
#define S_IFCHR 0020000
#endif
#ifndef S_IFDIR
#define S_IFDIR 0040000
#endif
#ifndef S_IFBLK
#define S_IFBLK 0060000
#endif
#ifndef S_IFREG
#define S_IFREG 0100000
#endif
#ifndef S_IFLNK
#define S_IFLNK 0120000
#endif
#ifndef S_IFSOCK
#define S_IFSOCK 0140000
#endif
#ifndef S_IRUSR
#define S_IRUSR 0400
#endif
#ifndef S_IWUSR
#define S_IWUSR 0200
#endif
#ifndef S_IXUSR
#define S_IXUSR 0100
#endif
#ifndef S_IRWXG
#define S_IRWXG 0070
#endif
#ifndef S_IRGRP
#define S_IRGRP 0040
#endif
#ifndef S_IWGRP
#define S_IWGRP 0020
#endif
#ifndef S_IXGRP
#define S_IXGRP 0010
#endif
#ifndef S_IRWXO
#define S_IRWXO 0007
#endif
#ifndef S_IROTH
#define S_IROTH 0004
#endif
#ifndef S_IWOTH
#define S_IWOTH 0002
#endif
#ifndef S_IXOTH
#define S_IXOTH 0001
#endif
/* MinGW's sys/stat.h has S_ISDIR / S_ISREG but not S_ISLNK. Windows
* tracks symlinks through FILE_ATTRIBUTE_REPARSE_POINT which isn't
* exposed in st_mode, so S_ISLNK always reports "not a symlink" - an
* acceptable simplification for PX4's symlink recreation path, which
* already handles the fall-through branch. */
#ifndef S_ISLNK
#define S_ISLNK(m) (0)
#endif
#ifndef S_ISFIFO
#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
#endif
#ifndef S_ISCHR
#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
#endif
#ifndef S_ISBLK
#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
#endif
#ifndef S_ISSOCK
#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
#endif
#ifndef _PX4_LSTAT_SHIM_DEFINED
#define _PX4_LSTAT_SHIM_DEFINED
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief lstat() compatibility shim.
*
* Windows CRT stat() does not expose symlink metadata in st_mode, so lstat()
* intentionally follows the same path as stat(). S_ISLNK() above therefore
* remains false and callers take their normal non-symlink branch.
*/
static inline int lstat(const char *path, struct stat *buf)
{
/* Windows has no per-link stat. Fall through to stat(); that's
* accurate enough because S_ISLNK above always returns 0, so
* callers fall into the non-symlink branch anyway. */
return stat(path, buf);
}
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,78 @@
/****************************************************************************
*
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file sys/statfs.h
*
* PX4 uses statfs() only to check whether SITL's synthetic storage
* directory looks like a working filesystem (f_blocks > 0). We route
* the query through GetDiskFreeSpaceExA on Windows - enough to make
* the arming check pass against %LOCALAPPDATA%\PX4.
*/
#pragma once
#include <sys/types.h>
#include <windows.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef long fsblkcnt_t;
typedef long fsfilcnt_t;
struct statfs {
unsigned long f_type;
unsigned long f_bsize;
unsigned long f_frsize;
fsblkcnt_t f_blocks;
fsblkcnt_t f_bfree;
fsblkcnt_t f_bavail;
fsfilcnt_t f_files;
fsfilcnt_t f_ffree;
unsigned long f_fsid;
unsigned long f_flags;
unsigned long f_namelen;
unsigned long f_spare[4];
};
/**
* @brief Return filesystem capacity information for @p path.
*
* Backed by GetDiskFreeSpaceExA and shaped like POSIX statfs().
*/
int statfs(const char *path, struct statfs *buf);
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,45 @@
/****************************************************************************
*
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file sys/time.h
*
* POSIX sys/time.h forwarding shim for Windows builds.
*/
#pragma once
#if defined(_MSC_VER) && !defined(__clang__)
#include <time.h>
#else
#include_next <sys/time.h>
#endif
@@ -0,0 +1,101 @@
/****************************************************************************
*
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file sys/types.h
*
* MinGW's <sys/types.h> omits the BSD-style unprefixed size aliases
* (uint, ushort, ulong) that glibc exports under _GNU_SOURCE. PX4 code
* uses `uint` directly in a couple of places - forward to the real
* header and add the aliases.
*/
#pragma once
#if defined(_MSC_VER) && !defined(__clang__)
#if defined(__has_include)
# if __has_include(<../ucrt/sys/types.h>)
# include <../ucrt/sys/types.h>
# endif
#endif
#include <stdint.h>
#include <stddef.h>
#include <basetsd.h>
#ifndef _PID_T_
/** @brief Process id type for native MSVC builds. */
typedef int pid_t;
#define _PID_T_
#endif
#ifndef _MODE_T_
/** @brief POSIX file mode bitmask type for native MSVC builds. */
typedef int mode_t;
#define _MODE_T_
#endif
#ifndef _OFF_T_DEFINED
/** @brief File offset type for native MSVC builds. */
typedef long off_t;
#define _OFF_T_DEFINED
#endif
#ifndef _SSIZE_T_DEFINED
/** @brief Signed size type matching Windows SSIZE_T. */
typedef SSIZE_T ssize_t;
#define _SSIZE_T_DEFINED
#endif
#ifndef _USECONDS_T_DEFINED
/** @brief Microsecond interval type used by usleep(). */
typedef unsigned int useconds_t;
#define _USECONDS_T_DEFINED
#endif
#else
#include_next <sys/types.h>
#endif
#ifndef _PX4_SYS_TYPES_ALIASES_DEFINED
#define _PX4_SYS_TYPES_ALIASES_DEFINED
/** @name BSD/GNU scalar aliases
*
* glibc exposes these names in PX4's POSIX build modes. Windows CRT headers do
* not, so the shim defines them once for shared code that uses the shorter
* spellings.
*
* @{
*/
typedef unsigned char u_char;
typedef unsigned short u_short;
typedef unsigned int u_int;
typedef unsigned long u_long;
typedef unsigned int uint;
typedef unsigned short ushort;
typedef unsigned long ulong;
typedef long long quad_t;
typedef unsigned long long u_quad_t;
/** @} */
#endif
@@ -0,0 +1,66 @@
/****************************************************************************
*
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file sys/un.h
*
* AF_UNIX was added to Windows 10 in build 17063 (April 2018) and is
* exposed through afunix.h. MinGW-w64 headers do not yet forward a
* POSIX-style <sys/un.h>, so we supply one that re-exposes the struct
* under the expected name. Windows' AF_UNIX supports SOCK_STREAM over
* file-system paths but not abstract namespace sockets - SITL only
* uses file-system paths, so this is sufficient for the daemon IPC.
*/
#pragma once
#ifndef _WIN32
# error "sys/un.h shim only valid on Windows"
#endif
#include <stddef.h>
#include <string.h>
#include <winsock2.h>
#include <afunix.h>
#ifndef UNIX_PATH_MAX
# define UNIX_PATH_MAX 108
#endif
typedef struct sockaddr_un sockaddr_un;
#ifndef SUN_LEN
# define SUN_LEN(ptr) ((socklen_t)(offsetof(struct sockaddr_un, sun_path) + strlen((ptr)->sun_path)))
#endif
/* afunix.h already provides struct sockaddr_un. Re-export sun_path/sun_family
* aliases if any translation unit expects them. afunix.h on Windows already
* names them that way, so no further work is needed. */
@@ -0,0 +1,96 @@
/****************************************************************************
*
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file sys/wait.h
*
* MinGW-w64 does not ship a POSIX waitpid/wait status header. PX4's
* Windows target does not support fork/exec semantics, but a number of
* third-party libraries still expect the wait status macros and a
* waitpid() declaration to exist. The implementation in
* posix_shim.cpp waits on a Windows process id/handle and synthesizes
* POSIX-style exit status words.
*/
#pragma once
#include <sys/types.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifndef WNOHANG
#define WNOHANG 0x00000001
#endif
#ifndef WUNTRACED
#define WUNTRACED 0x00000002
#endif
#ifndef WCONTINUED
#define WCONTINUED 0x00000008
#endif
#ifndef WEXITSTATUS
#define WEXITSTATUS(status) (((status) >> 8) & 0xff)
#endif
#ifndef WTERMSIG
#define WTERMSIG(status) ((status) & 0x7f)
#endif
#ifndef WSTOPSIG
#define WSTOPSIG(status) WEXITSTATUS(status)
#endif
#ifndef WIFEXITED
#define WIFEXITED(status) (WTERMSIG(status) == 0)
#endif
#ifndef WIFSIGNALED
#define WIFSIGNALED(status) (WTERMSIG(status) != 0 && WTERMSIG(status) != 0x7f)
#endif
#ifndef WIFSTOPPED
#define WIFSTOPPED(status) (WTERMSIG(status) == 0x7f)
#endif
#ifndef WIFCONTINUED
#define WIFCONTINUED(status) ((status) == 0xffff)
#endif
/**
* @brief Wait for a Windows process id and synthesize a POSIX wait status.
*
* @param pid Process id to wait for.
* @param status Optional POSIX wait status output.
* @param options Supports WNOHANG; other options are accepted for source
* compatibility.
* @return @p pid on completion, 0 for WNOHANG timeout, or -1 with errno set.
*/
pid_t waitpid(pid_t pid, int *status, int options);
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,143 @@
/****************************************************************************
*
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file syslog.h
*
* MinGW has no <syslog.h>. Most PX4 call sites only include the header
* (to satisfy printf-style macros through other logging layers) rather
* than actually calling syslog(), so we provide a header with the
* standard priority levels and a syslog() that forwards to stderr.
*/
#pragma once
#include <stdarg.h>
#include <stdio.h>
#define LOG_KERN (0 << 3)
#define LOG_USER (1 << 3)
#define LOG_MAIL (2 << 3)
#define LOG_DAEMON (3 << 3)
#define LOG_AUTH (4 << 3)
#define LOG_SYSLOG (5 << 3)
#define LOG_LPR (6 << 3)
#define LOG_NEWS (7 << 3)
#define LOG_UUCP (8 << 3)
#define LOG_CRON (9 << 3)
#define LOG_AUTHPRIV (10 << 3)
#define LOG_FTP (11 << 3)
#define LOG_LOCAL0 (16 << 3)
#define LOG_LOCAL1 (17 << 3)
#define LOG_LOCAL2 (18 << 3)
#define LOG_LOCAL3 (19 << 3)
#define LOG_LOCAL4 (20 << 3)
#define LOG_LOCAL5 (21 << 3)
#define LOG_LOCAL6 (22 << 3)
#define LOG_LOCAL7 (23 << 3)
#define LOG_EMERG 0
#define LOG_ALERT 1
#define LOG_CRIT 2
#define LOG_ERR 3
#define LOG_WARNING 4
#define LOG_NOTICE 5
#define LOG_INFO 6
#define LOG_DEBUG 7
#define LOG_PID 0x01
#define LOG_CONS 0x02
#define LOG_NDELAY 0x08
#define LOG_NOWAIT 0x10
#define LOG_PERROR 0x20
#define LOG_PRIMASK 0x07
#define LOG_FACMASK 0x03f8
#define LOG_PRI(p) ((p) & LOG_PRIMASK)
#define LOG_FAC(p) (((p) & LOG_FACMASK) >> 3)
#define LOG_MAKEPRI(fac, pri) ((fac) | (pri))
#define LOG_MASK(pri) (1 << (pri))
#define LOG_UPTO(pri) ((1 << ((pri) + 1)) - 1)
#ifdef __cplusplus
extern "C" {
#endif
static int px4_syslog_mask = LOG_UPTO(LOG_DEBUG);
/** @brief Accept syslog identity/options; no persistent Windows sink is opened. */
static inline void openlog(const char *ident, int option, int facility)
{
(void)ident; (void)option; (void)facility;
}
/** @brief Close the syslog sink; no-op for the stderr-backed shim. */
static inline void closelog(void) {}
/**
* @brief Set the active syslog priority mask.
*
* @return Previous mask, matching POSIX setlogmask().
*/
static inline int setlogmask(int maskpri)
{
const int old_mask = px4_syslog_mask;
if (maskpri != 0) {
px4_syslog_mask = maskpri;
}
return old_mask;
}
/** @brief Write a masked syslog message to stderr with a trailing newline. */
static inline void vsyslog(int priority, const char *fmt, va_list ap)
{
if ((LOG_MASK(LOG_PRI(priority)) & px4_syslog_mask) == 0) {
return;
}
vfprintf(stderr, fmt, ap);
fputc('\n', stderr);
}
/** @brief Variadic syslog wrapper around vsyslog(). */
static inline void syslog(int priority, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vsyslog(priority, fmt, ap);
va_end(ap);
}
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,256 @@
/****************************************************************************
*
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file termios.h
*
* Windows termios.h shim for PX4 SITL.
*
* MinGW-w64 does not ship a termios header. SITL drivers that touch
* serial UARTs (GPS, RC, telemetry radios, etc.) include <termios.h>
* unconditionally. We expose the full IEEE Std 1003.1-2017 structure
* and constants so the code compiles, and route the handful of termios
* functions to stubs that return -ENOSYS. Real serial I/O on Windows
* would go through CreateFileA("\\\\.\\COMx", ...) + SetCommState;
* that is out of scope for the base SITL port but this stub surface
* leaves room to add it later without touching any driver code.
*/
#pragma once
#include <sys/types.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef unsigned int tcflag_t;
typedef unsigned int speed_t;
typedef unsigned char cc_t;
#define NCCS 32
/**
* @brief POSIX terminal attribute container.
*
* Native Windows SITL currently exposes this structure for driver source
* compatibility only; tc* functions return -1/ENOSYS until a COM-port backed
* implementation is added.
*/
struct termios {
tcflag_t c_iflag;
tcflag_t c_oflag;
tcflag_t c_cflag;
tcflag_t c_lflag;
cc_t c_line;
cc_t c_cc[NCCS];
speed_t c_ispeed;
speed_t c_ospeed;
};
/* c_iflag - input modes */
#define IGNBRK 0000001
#define BRKINT 0000002
#define IGNPAR 0000004
#define PARMRK 0000010
#define INPCK 0000020
#define ISTRIP 0000040
#define INLCR 0000100
#define IGNCR 0000200
#define ICRNL 0000400
#define IUCLC 0001000
#define IXON 0002000
#define IXANY 0004000
#define IXOFF 0010000
#define IMAXBEL 0020000
#define IUTF8 0040000
/* c_oflag - output modes */
#define OPOST 0000001
#define OLCUC 0000002
#define ONLCR 0000004
#define OCRNL 0000010
#define ONOCR 0000020
#define ONLRET 0000040
#define OFILL 0000100
#define OFDEL 0000200
#define NLDLY 0000400
#define NL0 0000000
#define NL1 0000400
#define CRDLY 0003000
#define CR0 0000000
#define CR1 0001000
#define CR2 0002000
#define CR3 0003000
#define TABDLY 0014000
#define TAB0 0000000
#define TAB1 0004000
#define TAB2 0010000
#define TAB3 0014000
#define BSDLY 0020000
#define BS0 0000000
#define BS1 0020000
#define VTDLY 0040000
#define VT0 0000000
#define VT1 0040000
#define FFDLY 0100000
#define FF0 0000000
#define FF1 0100000
/* c_cflag - control modes */
#define CSIZE 0000060
#define CS5 0000000
#define CS6 0000020
#define CS7 0000040
#define CS8 0000060
#define CSTOPB 0000100
#define CREAD 0000200
#define PARENB 0000400
#define PARODD 0001000
#define HUPCL 0002000
#define CLOCAL 0004000
#define CMSPAR 010000000000
#define CRTSCTS 020000000000
/* c_lflag - local modes */
#define ISIG 0000001
#define ICANON 0000002
#define XCASE 0000004
#define ECHO 0000010
#define ECHOE 0000020
#define ECHOK 0000040
#define ECHONL 0000100
#define NOFLSH 0000200
#define TOSTOP 0000400
#define ECHOCTL 0001000
#define ECHOPRT 0002000
#define ECHOKE 0004000
#define FLUSHO 0010000
#define PENDIN 0040000
#define IEXTEN 0100000
#define EXTPROC 0200000
/* c_cc indices */
#define VINTR 0
#define VQUIT 1
#define VERASE 2
#define VKILL 3
#define VEOF 4
#define VTIME 5
#define VMIN 6
#define VSWTC 7
#define VSTART 8
#define VSTOP 9
#define VSUSP 10
#define VEOL 11
#define VREPRINT 12
#define VDISCARD 13
#define VWERASE 14
#define VLNEXT 15
#define VEOL2 16
/* optional_actions for tcsetattr */
#define TCSANOW 0
#define TCSADRAIN 1
#define TCSAFLUSH 2
/* queue_selector for tcflush */
#define TCIFLUSH 0
#define TCOFLUSH 1
#define TCIOFLUSH 2
/* action for tcflow */
#define TCOOFF 0
#define TCOON 1
#define TCIOFF 2
#define TCION 3
/* Baud rates - numeric values (Linux encodes as bitmask in c_cflag;
* PX4 never inspects these beyond round-tripping through the struct). */
#define B0 0
#define B50 50
#define B75 75
#define B110 110
#define B134 134
#define B150 150
#define B200 200
#define B300 300
#define B600 600
#define B1200 1200
#define B1800 1800
#define B2400 2400
#define B4800 4800
#define B9600 9600
#define B19200 19200
#define B38400 38400
#define B57600 57600
#define B115200 115200
#define B230400 230400
#define B460800 460800
#define B500000 500000
#define B576000 576000
#define B921600 921600
#define B1000000 1000000
#define B1152000 1152000
#define B1500000 1500000
#define B2000000 2000000
#define B2500000 2500000
#define B3000000 3000000
#define B3500000 3500000
#define B4000000 4000000
/** @name Terminal attribute operations
*
* Declared for POSIX source compatibility. The Windows backend stubs these
* functions today because PX4 SITL does not talk to native serial devices
* through termios.
*
* @{
*/
int tcgetattr(int fd, struct termios *termios_p);
int tcsetattr(int fd, int optional_actions, const struct termios *termios_p);
int tcflush(int fd, int queue_selector);
int tcdrain(int fd);
int tcflow(int fd, int action);
int tcsendbreak(int fd, int duration);
pid_t tcgetsid(int fd);
int cfsetispeed(struct termios *termios_p, speed_t speed);
int cfsetospeed(struct termios *termios_p, speed_t speed);
int cfsetspeed(struct termios *termios_p, speed_t speed);
speed_t cfgetispeed(const struct termios *termios_p);
speed_t cfgetospeed(const struct termios *termios_p);
void cfmakeraw(struct termios *termios_p);
/** @} */
#ifdef __cplusplus
}
#endif
+167
View File
@@ -0,0 +1,167 @@
/****************************************************************************
*
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file time.h
*
* MinGW ships <time.h> with the Windows _s variants but not POSIX's
* _r reentrant forms. The argument orders differ (_s takes buffer first,
* _r takes the input first) so we can't just #define. Provide thin
* inline wrappers.
*/
#pragma once
#if defined(_MSC_VER) && !defined(__clang__)
#if defined(__has_include)
# if __has_include(<../ucrt/time.h>)
# include <../ucrt/time.h>
# else
# include <time.h>
# endif
#else
#include <time.h>
#endif
#include <sys/types.h>
typedef int clockid_t;
#ifndef CLOCK_REALTIME
#define CLOCK_REALTIME 0
#endif
#ifndef CLOCK_MONOTONIC
#define CLOCK_MONOTONIC 1
#endif
#ifndef CLOCK_BOOTTIME
#define CLOCK_BOOTTIME CLOCK_MONOTONIC
#endif
#ifndef CLOCK_REALTIME_COARSE
#define CLOCK_REALTIME_COARSE CLOCK_REALTIME
#endif
#ifndef CLOCK_MONOTONIC_COARSE
#define CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC
#endif
#ifndef _TIMEVAL_DEFINED
#define _TIMEVAL_DEFINED
struct timeval {
long tv_sec;
long tv_usec;
};
#endif
#else
#include_next <time.h>
#endif
#ifndef _PX4_TIME_R_SHIM_DEFINED
#define _PX4_TIME_R_SHIM_DEFINED
#ifdef __cplusplus
extern "C" {
#endif
#if defined(_MSC_VER) && !defined(__clang__)
/** @brief POSIX clock_gettime() backed by Windows high-resolution timers. */
int clock_gettime(clockid_t clk_id, struct timespec *tp);
/** @brief POSIX clock_settime() compatibility entry point. */
int clock_settime(clockid_t clk_id, const struct timespec *tp);
/** @brief Fill a POSIX timeval with the current wall-clock time. */
int gettimeofday(struct timeval *tv, void *tz);
/** @brief Sleep for the requested interval, reporting no remaining time. */
int nanosleep(const struct timespec *req, struct timespec *rem);
#endif
/** @brief Thread-safe UTC conversion using the Windows gmtime_s() order. */
static inline struct tm *gmtime_r(const time_t *timep, struct tm *result)
{
if (!timep || !result) { return NULL; }
return (gmtime_s(result, timep) == 0) ? result : NULL;
}
/** @brief Thread-safe local-time conversion using the Windows localtime_s(). */
static inline struct tm *localtime_r(const time_t *timep, struct tm *result)
{
if (!timep || !result) { return NULL; }
return (localtime_s(result, timep) == 0) ? result : NULL;
}
/** @brief Thread-safe asctime() wrapper; @p buf must hold at least 26 bytes. */
static inline char *asctime_r(const struct tm *tm, char *buf)
{
if (!tm || !buf) { return NULL; }
/* POSIX requires a 26-byte buffer; match that to asctime_s. */
return (asctime_s(buf, 26, tm) == 0) ? buf : NULL;
}
/** @brief Thread-safe ctime() wrapper; @p buf must hold at least 26 bytes. */
static inline char *ctime_r(const time_t *timep, char *buf)
{
if (!timep || !buf) { return NULL; }
return (ctime_s(buf, 26, timep) == 0) ? buf : NULL;
}
#ifndef timerisset
#define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec)
#endif
#ifndef timerclear
#define timerclear(tvp) do { (tvp)->tv_sec = 0; (tvp)->tv_usec = 0; } while (0)
#endif
#ifndef timercmp
#define timercmp(a, b, CMP) (((a)->tv_sec == (b)->tv_sec) ? ((a)->tv_usec CMP (b)->tv_usec) : ((a)->tv_sec CMP (b)->tv_sec))
#endif
#ifndef timeradd
#define timeradd(a, b, result) \
do { \
(result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \
(result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \
if ((result)->tv_usec >= 1000000) { \
++(result)->tv_sec; \
(result)->tv_usec -= 1000000; \
} \
} while (0)
#endif
#ifndef timersub
#define timersub(a, b, result) \
do { \
(result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
(result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
if ((result)->tv_usec < 0) { \
--(result)->tv_sec; \
(result)->tv_usec += 1000000; \
} \
} while (0)
#endif
#ifdef __cplusplus
}
#endif
#endif /* _PX4_TIME_R_SHIM_DEFINED */
@@ -0,0 +1,319 @@
/****************************************************************************
*
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file unistd.h
*
* unistd.h extension shim for PX4 SITL on Windows.
*
* MinGW ships a minimal <unistd.h> but omits POSIX helpers that PX4 and
* third-party code use directly (pipe, fsync, symlink, dprintf, sysconf,
* process/session helpers, environment setters, hard links).
* Forward to the real header via #include_next and layer the missing
* pieces on top using Win32 CRT equivalents (_pipe, _commit, _write)
* or Win32 APIs (CreateSymbolicLinkA, GetSystemInfo).
*/
#pragma once
#if defined(_MSC_VER) && !defined(__clang__)
#include <sys/types.h>
#else
#include_next <unistd.h>
#endif
#include <io.h>
#include <stdarg.h>
#include <stdio.h>
#include <windows.h>
/* POSIX standard fd numbers - MinGW defines them via io.h but belt-and-suspenders. */
#ifndef STDIN_FILENO
#define STDIN_FILENO 0
#endif
#ifndef STDOUT_FILENO
#define STDOUT_FILENO 1
#endif
#ifndef STDERR_FILENO
#define STDERR_FILENO 2
#endif
#ifndef F_OK
#define F_OK 0
#endif
#ifndef X_OK
#define X_OK 1
#endif
#ifndef W_OK
#define W_OK 2
#endif
#ifndef R_OK
#define R_OK 4
#endif
/* POSIX sysconf selectors that MinGW doesn't ship. Numerical values
* don't need to match Linux - only our own sysconf() implementation
* inspects them. */
#ifndef _SC_PAGESIZE
#define _SC_PAGESIZE 30
#endif
#ifndef _SC_PAGE_SIZE
#define _SC_PAGE_SIZE _SC_PAGESIZE
#endif
#ifndef _SC_CLK_TCK
#define _SC_CLK_TCK 2
#endif
#ifndef _SC_NPROCESSORS_ONLN
#define _SC_NPROCESSORS_ONLN 84
#endif
#ifndef _SC_NPROCESSORS_CONF
#define _SC_NPROCESSORS_CONF 83
#endif
#ifndef _SC_OPEN_MAX
#define _SC_OPEN_MAX 4
#endif
#ifndef _SC_HOST_NAME_MAX
#define _SC_HOST_NAME_MAX 180
#endif
#ifndef _SC_LOGIN_NAME_MAX
#define _SC_LOGIN_NAME_MAX 71
#endif
#ifndef _SC_PHYS_PAGES
#define _SC_PHYS_PAGES 85
#endif
#ifndef _SC_AVPHYS_PAGES
#define _SC_AVPHYS_PAGES 86
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if defined(_MSC_VER) && !defined(__clang__)
/** @brief Sleep for at least @p usec microseconds using Windows Sleep(). */
static inline int usleep(useconds_t usec)
{
Sleep((DWORD)((usec + 999U) / 1000U));
return 0;
}
/** @brief Sleep for at least @p seconds seconds using Windows Sleep(). */
static inline unsigned int sleep(unsigned int seconds)
{
Sleep(seconds * 1000U);
return 0;
}
#endif
/* POSIX pipe(fd[2]) - default to 64 KiB buffer and binary mode. */
#ifndef _PX4_PIPE_SHIM_DEFINED
#define _PX4_PIPE_SHIM_DEFINED
/** @brief Create a binary CRT pipe with a 64 KiB buffer. */
static inline int pipe(int fds[2]) { return _pipe(fds, 65536, 0x8000 /* _O_BINARY */); }
/**
* @brief pipe2() compatibility wrapper.
*
* Windows CRT pipes do not expose POSIX pipe2 flags; the shim accepts the
* argument and creates the same binary pipe as pipe().
*/
static inline int pipe2(int fds[2], int flags)
{
(void)flags;
return pipe(fds);
}
#endif
/* POSIX fsync(fd) - forwards to _commit (flushes the CRT fd's buffers
* down to the underlying HANDLE and flushes the HANDLE to disk). */
#ifndef _PX4_FSYNC_SHIM_DEFINED
#define _PX4_FSYNC_SHIM_DEFINED
static inline int fsync(int fd) { return _commit(fd); }
#endif
/* fdatasync: Windows has no separate metadata/data flush. Treat it as
* equivalent to fsync (POSIX allows this; it's just stricter). */
#ifndef _PX4_FDATASYNC_SHIM_DEFINED
#define _PX4_FDATASYNC_SHIM_DEFINED
static inline int fdatasync(int fd) { return _commit(fd); }
#endif
/* POSIX sysconf - implemented in posix_shim.cpp so we can use
* <windows.h>'s GetSystemInfo / GlobalMemoryStatusEx without forcing
* every translation unit to drag in <windows.h>. */
#ifndef _PX4_SYSCONF_SHIM_DEFINED
#define _PX4_SYSCONF_SHIM_DEFINED
/**
* @brief Query host limits for the POSIX selectors PX4 uses.
*
* Implemented in the Windows backend so page size, processor count, and memory
* values come from GetSystemInfo/GlobalMemoryStatusEx.
*/
long sysconf(int name);
#endif
/* POSIX symlink(target, linkpath) - forwards to CreateSymbolicLinkA
* (requires the SE_CREATE_SYMBOLIC_LINK_NAME privilege or Windows 10
* developer-mode). Returns -1 with errno = EPERM if the user lacks
* the privilege. */
#ifndef _PX4_SYMLINK_SHIM_DEFINED
#define _PX4_SYMLINK_SHIM_DEFINED
/**
* @brief Create a filesystem symbolic link.
*
* @return 0 on success, -1 with errno set. EPERM indicates missing Windows
* symlink privilege or disabled developer mode.
*/
int symlink(const char *target, const char *linkpath);
#endif
/* POSIX readlink - Windows has no O(1) path-to-reparse-target readout;
* fall through to DeviceIoControl on the reparse point. The base SITL
* build doesn't follow symlinks, so the shim lives in posix_shim.cpp. */
#ifndef _PX4_READLINK_SHIM_DEFINED
#define _PX4_READLINK_SHIM_DEFINED
/**
* @brief Read the target of a filesystem reparse-point symlink.
*
* @return Number of bytes copied into @p buf, or -1 with errno set.
*/
ssize_t readlink(const char *path, char *buf, size_t bufsiz);
#endif
/* POSIX truncate(path, length) - forwards to CreateFileA + SetEndOfFile
* in posix_shim.cpp. ftruncate on a CRT fd uses _chsize_s. */
#ifndef _PX4_TRUNCATE_SHIM_DEFINED
#define _PX4_TRUNCATE_SHIM_DEFINED
/** @brief Truncate a file by path using CreateFileA/SetEndOfFile. */
int truncate(const char *path, off_t length);
#endif
/* POSIX link(oldpath, newpath) - maps onto CreateHardLinkA via
* posix_shim.cpp. */
#ifndef _PX4_LINK_SHIM_DEFINED
#define _PX4_LINK_SHIM_DEFINED
/** @brief Create a hard link using CreateHardLinkA. */
int link(const char *existing_path, const char *new_path);
#endif
/* POSIX realpath fallback - CRT _fullpath returns the canonical path. */
#ifndef _PX4_REALPATH_SHIM_DEFINED
#define _PX4_REALPATH_SHIM_DEFINED
#include <stdlib.h>
/** @brief Resolve a path to an absolute CRT path using _fullpath(). */
static inline char *realpath(const char *path, char *resolved_path)
{
return _fullpath(resolved_path, path, resolved_path ? 260 : 0);
}
#endif
/* POSIX dprintf / vdprintf - forward to _write on the CRT fd. */
#ifndef _PX4_DPRINTF_SHIM_DEFINED
#define _PX4_DPRINTF_SHIM_DEFINED
/** @brief Formatted write to a CRT file descriptor. */
static inline int vdprintf(int fd, const char *fmt, va_list ap)
{
char buf[1024];
int n = vsnprintf(buf, sizeof(buf), fmt, ap);
if (n <= 0) { return n; }
if ((size_t)n >= sizeof(buf)) { n = (int)sizeof(buf) - 1; }
return (int)_write(fd, buf, (unsigned)n);
}
/** @brief Variadic formatted write to a CRT file descriptor. */
static inline int dprintf(int fd, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
int n = vdprintf(fd, fmt, ap);
va_end(ap);
return n;
}
#endif
#ifndef TEMP_FAILURE_RETRY
#define TEMP_FAILURE_RETRY(expression) (expression)
#endif
/* POSIX getpagesize - Windows has GetSystemInfo.dwPageSize (typically
* 4096 on x86/x64, 16384 on ARM64). */
#ifndef _PX4_GETPAGESIZE_SHIM_DEFINED
#define _PX4_GETPAGESIZE_SHIM_DEFINED
/** @brief Return the host memory page size in bytes. */
int getpagesize(void);
#endif
/* POSIX/BSD process and environment helpers that MinGW does not
* declare. These are implemented in posix_shim.cpp with Windows-backed
* compatibility semantics suitable for PX4 and embedded host apps. */
#ifndef _PX4_GETPPID_SHIM_DEFINED
#define _PX4_GETPPID_SHIM_DEFINED
/** @brief Return the parent process id when Windows can discover it. */
pid_t getppid(void);
#endif
#ifndef _PX4_SETSID_SHIM_DEFINED
#define _PX4_SETSID_SHIM_DEFINED
/** @brief Create a best-effort process session; returns the current pid. */
pid_t setsid(void);
#endif
#ifndef _PX4_GETSID_SHIM_DEFINED
#define _PX4_GETSID_SHIM_DEFINED
/** @brief Return the best-effort session id for @p pid. */
pid_t getsid(pid_t pid);
#endif
#ifndef _PX4_DAEMON_SHIM_DEFINED
#define _PX4_DAEMON_SHIM_DEFINED
/**
* @brief daemon() compatibility shim.
*
* Windows cannot fork and detach in the POSIX sense; the implementation applies
* the requested cwd/stdio behavior where possible and otherwise reports
* success for callers that only need a background-compatible code path.
*/
int daemon(int nochdir, int noclose);
#endif
#ifndef _PX4_SETENV_SHIM_DEFINED
#define _PX4_SETENV_SHIM_DEFINED
/** @brief Set an environment variable using the Windows CRT environment. */
int setenv(const char *name, const char *value, int overwrite);
#endif
#ifndef _PX4_UNSETENV_SHIM_DEFINED
#define _PX4_UNSETENV_SHIM_DEFINED
/** @brief Remove an environment variable using the Windows CRT environment. */
int unsetenv(const char *name);
#endif
#ifdef __cplusplus
}
#endif

Some files were not shown because too many files have changed in this diff Show More