def SysUtsNameAPI : PublicAPI<"sys/utsname.h"> {
let Types = ["struct utsname"];
}
+
+def SpawnAPI : PublicAPI<"spawn.h"> {
+ let Types = ["mode_t", "posix_spawn_file_actions_t"];
+}
libc.src.signal.sigfillset
libc.src.signal.signal
+ # spawn.h entrypoints
+ libc.src.spawn.posix_spawn_file_actions_addclose
+ libc.src.spawn.posix_spawn_file_actions_adddup2
+ libc.src.spawn.posix_spawn_file_actions_addopen
+ libc.src.spawn.posix_spawn_file_actions_destroy
+ libc.src.spawn.posix_spawn_file_actions_init
+
# threads.h entrypoints
libc.src.threads.call_once
libc.src.threads.cnd_broadcast
.llvm-libc-macros.sched_macros
)
+add_gen_header(
+ spawn
+ DEF_FILE spawn.h.def
+ GEN_HDR spawn.h
+ DEPENDS
+ .llvm_libc_common_h
+ .llvm-libc-types.mode_t
+ .llvm-libc-types.posix_spawn_file_actions_t
+)
+
# TODO: Not all platforms will have a include/sys directory. Add the sys
# directory and the targets for sys/*.h files conditional to the OS requiring
# them.
add_header(off_t HDR off_t.h)
add_header(once_flag HDR once_flag.h DEPENDS .__futex_word)
add_header(pid_t HDR pid_t.h)
+add_header(posix_spawn_file_actions_t HDR posix_spawn_file_actions_t.h)
add_header(pthread_attr_t HDR pthread_attr_t.h DEPENDS .size_t)
add_header(pthread_key_t HDR pthread_key_t.h)
add_header(pthread_mutex_t HDR pthread_mutex_t.h DEPENDS .__futex_word .__mutex_type)
--- /dev/null
+//===-- Definition of type posix_spawn_file_actions_t ---------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __LLVM_LIBC_TYPES_POSIX_SPAWN_FILE_ACTIONS_T_T_H
+#define __LLVM_LIBC_TYPES_POSIX_SPAWN_FILE_ACTIONS_T_T_H
+
+typedef struct {
+ void *__front;
+ void *__back;
+} posix_spawn_file_actions_t;
+
+#endif // __LLVM_LIBC_TYPES_POSIX_SPAWN_FILE_ACTIONS_T_T_H
--- /dev/null
+//===-- POSIX header spawn.h ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SPAWN_H
+#define LLVM_LIBC_SPAWN_H
+
+#include <__llvm-libc-common.h>
+
+%%public_api()
+
+#endif // LLVM_LIBC_SPAWN_H
def AtForkCallbackT : NamedType<"__atfork_callback_t">;
+def PosixSpawnFileActionsT : NamedType<"posix_spawn_file_actions_t">;
+def PosixSpawnFileActionsTPtr : PtrType<PosixSpawnFileActionsT>;
+def PosixSpawnFileActionsTRestrictedPtr : RestrictedPtrType<PosixSpawnFileActionsT>;
+
def POSIX : StandardSpec<"POSIX"> {
PtrType CharPtr = PtrType<CharType>;
RestrictedPtrType RestrictedCharPtr = RestrictedPtrType<CharType>;
[] // Functions
>;
+ HeaderSpec Spawn = HeaderSpec<
+ "spawn.h",
+ [], // Macros
+ [PosixSpawnFileActionsT, ModeTType],
+ [], // Enumerations
+ [
+ FunctionSpec<
+ "posix_spawn_file_actions_addclose",
+ RetValSpec<IntType>,
+ [ArgSpec<PosixSpawnFileActionsTPtr>, ArgSpec<IntType>]
+ >,
+ FunctionSpec<
+ "posix_spawn_file_actions_adddup2",
+ RetValSpec<IntType>,
+ [ArgSpec<PosixSpawnFileActionsTPtr>, ArgSpec<IntType>, ArgSpec<IntType>]
+ >,
+ FunctionSpec<
+ "posix_spawn_file_actions_addopen",
+ RetValSpec<IntType>,
+ [ArgSpec<PosixSpawnFileActionsTRestrictedPtr>, ArgSpec<IntType>,
+ ArgSpec<ConstCharRestrictedPtr>, ArgSpec<IntType>, ArgSpec<ModeTType>]
+ >,
+ FunctionSpec<
+ "posix_spawn_file_actions_destroy",
+ RetValSpec<IntType>,
+ [ArgSpec<PosixSpawnFileActionsTPtr>]
+ >,
+ FunctionSpec<
+ "posix_spawn_file_actions_init",
+ RetValSpec<IntType>,
+ [ArgSpec<PosixSpawnFileActionsTPtr>]
+ >,
+ ]
+ >;
+
let Headers = [
CType,
Dirent,
FCntl,
PThread,
Signal,
+ Spawn,
StdIO,
StdLib,
SysIOctl,
# since assert uses the signal API, we disable assert also.
# add_subdirectory(assert)
add_subdirectory(signal)
+add_subdirectory(spawn)
add_subdirectory(threads)
add_subdirectory(time)
--- /dev/null
+add_header_library(
+ file_actions
+ HDRS
+ file_actions.h
+ DEPENDS
+ libc.include.spawn
+)
+
+add_entrypoint_object(
+ posix_spawn_file_actions_init
+ SRCS
+ posix_spawn_file_actions_init.cpp
+ HDRS
+ posix_spawn_file_actions_init.h
+ DEPENDS
+ libc.include.spawn
+)
+
+add_entrypoint_object(
+ posix_spawn_file_actions_destroy
+ SRCS
+ posix_spawn_file_actions_destroy.cpp
+ HDRS
+ posix_spawn_file_actions_destroy.h
+ DEPENDS
+ .file_actions
+ libc.include.errno
+ libc.include.spawn
+)
+
+add_entrypoint_object(
+ posix_spawn_file_actions_adddup2
+ SRCS
+ posix_spawn_file_actions_adddup2.cpp
+ HDRS
+ posix_spawn_file_actions_adddup2.h
+ DEPENDS
+ .file_actions
+ libc.include.errno
+ libc.include.spawn
+)
+
+add_entrypoint_object(
+ posix_spawn_file_actions_addopen
+ SRCS
+ posix_spawn_file_actions_addopen.cpp
+ HDRS
+ posix_spawn_file_actions_addopen.h
+ DEPENDS
+ .file_actions
+ libc.include.errno
+ libc.include.spawn
+)
+
+add_entrypoint_object(
+ posix_spawn_file_actions_addclose
+ SRCS
+ posix_spawn_file_actions_addclose.cpp
+ HDRS
+ posix_spawn_file_actions_addclose.h
+ DEPENDS
+ .file_actions
+ libc.include.errno
+ libc.include.spawn
+)
--- /dev/null
+//===-- Spawn file actions -------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SPAWN_FILE_ACTIONS_H
+#define LLVM_LIBC_SRC_SPAWN_FILE_ACTIONS_H
+
+#include <spawn.h> // For mode_t
+#include <stdint.h>
+
+namespace __llvm_libc {
+
+struct BaseSpawnFileAction {
+ enum ActionType {
+ OPEN = 111,
+ CLOSE = 222,
+ DUP2 = 333,
+ };
+
+ ActionType type;
+ BaseSpawnFileAction *next;
+};
+
+struct SpawnFileOpenAction : public BaseSpawnFileAction {
+ const char *path;
+ int fd;
+ int oflag;
+ mode_t mode;
+};
+
+struct SpawnFileCloseAction : public BaseSpawnFileAction {
+ int fd;
+};
+
+struct SpawnFileDup2Action : public BaseSpawnFileAction {
+ int fd;
+ int newfd;
+};
+
+inline void enque_spawn_action(posix_spawn_file_actions_t *actions,
+ BaseSpawnFileAction *act) {
+ if (actions->__back != nullptr) {
+ auto *back = reinterpret_cast<BaseSpawnFileAction *>(actions->__back);
+ back->next = act;
+ actions->__back = act;
+ } else {
+ // First action is being added.
+ actions->__front = actions->__back = act;
+ }
+}
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_SPAWN_FILE_ACTIONS_H
--- /dev/null
+//===-- Implementation of posix_spawn_file_actions_addclose ---------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "posix_spawn_file_actions_addclose.h"
+
+#include "file_actions.h"
+#include "src/__support/common.h"
+
+#include <errno.h>
+#include <spawn.h>
+#include <stdlib.h> // For malloc
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(int, posix_spawn_file_actions_addclose,
+ (posix_spawn_file_actions_t *__restrict actions, int fd)) {
+ if (actions == nullptr)
+ return EINVAL;
+ if (fd < 0)
+ return EBADF;
+
+ auto *act = reinterpret_cast<SpawnFileCloseAction *>(
+ malloc(sizeof(SpawnFileCloseAction)));
+ if (act == nullptr)
+ return ENOMEM;
+
+ act->type = BaseSpawnFileAction::CLOSE;
+ act->fd = fd;
+ enque_spawn_action(actions, act);
+ return 0;
+}
+
+} // namespace __llvm_libc
--- /dev/null
+//===-- Impl header for posix_spawn_file_actions_addclose -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SPAWN_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE_H
+#define LLVM_LIBC_SRC_SPAWN_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE_H
+
+#include <spawn.h>
+
+namespace __llvm_libc {
+
+int posix_spawn_file_actions_addclose(
+ posix_spawn_file_actions_t *__restrict actions, int fd);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_SPAWN_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE_H
--- /dev/null
+//===-- Implementation of posix_spawn_file_actions_adddup2 ----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "posix_spawn_file_actions_adddup2.h"
+
+#include "file_actions.h"
+#include "src/__support/common.h"
+
+#include <errno.h>
+#include <spawn.h>
+#include <stdlib.h> // For malloc
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(int, posix_spawn_file_actions_adddup2,
+ (posix_spawn_file_actions_t * actions, int fd, int newfd)) {
+ if (actions == nullptr)
+ return EINVAL;
+ if (fd < 0 || newfd < 0)
+ return EBADF;
+
+ auto *act = reinterpret_cast<SpawnFileDup2Action *>(
+ malloc(sizeof(SpawnFileDup2Action)));
+ if (act == nullptr)
+ return ENOMEM;
+
+ act->type = BaseSpawnFileAction::DUP2;
+ act->fd = fd;
+ act->newfd = newfd;
+ act->next = nullptr;
+ enque_spawn_action(actions, act);
+ return 0;
+}
+
+} // namespace __llvm_libc
--- /dev/null
+//===-- Impl header for posix_spawn_file_actions_adddup2 --------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SPAWN_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2_H
+#define LLVM_LIBC_SRC_SPAWN_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2_H
+
+#include <spawn.h>
+
+namespace __llvm_libc {
+
+int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *actions,
+ int fd, int newfd);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_SPAWN_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2_H
--- /dev/null
+//===-- Implementation of posix_spawn_file_actions_addopen ----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "posix_spawn_file_actions_addopen.h"
+
+#include "file_actions.h"
+#include "src/__support/common.h"
+
+#include <errno.h>
+#include <spawn.h>
+#include <stdlib.h> // For malloc
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(int, posix_spawn_file_actions_addopen,
+ (posix_spawn_file_actions_t *__restrict actions, int fd,
+ const char *__restrict path, int oflag, mode_t mode)) {
+ if (actions == nullptr)
+ return EINVAL;
+ if (fd < 0)
+ return EBADF;
+
+ auto *act = reinterpret_cast<SpawnFileOpenAction *>(
+ malloc(sizeof(SpawnFileOpenAction)));
+ if (act == nullptr)
+ return ENOMEM;
+
+ act->type = BaseSpawnFileAction::OPEN;
+ act->fd = fd;
+ act->path = path;
+ act->oflag = oflag;
+ act->mode = mode;
+ act->next = nullptr;
+ enque_spawn_action(actions, act);
+ return 0;
+}
+
+} // namespace __llvm_libc
--- /dev/null
+//===-- Impl header for posix_spawn_file_actions_addopen --------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SPAWN_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN_H
+#define LLVM_LIBC_SRC_SPAWN_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN_H
+
+#include <spawn.h>
+
+namespace __llvm_libc {
+
+int posix_spawn_file_actions_addopen(
+ posix_spawn_file_actions_t *__restrict actions, int fd,
+ const char *__restrict path, int oflag, mode_t mode);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_SPAWN_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN_H
--- /dev/null
+//===-- Implementation of posix_spawn_file_actions_destroy ----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "posix_spawn_file_actions_destroy.h"
+
+#include "file_actions.h"
+#include "src/__support/common.h"
+
+#include <errno.h>
+#include <spawn.h>
+#include <stdlib.h> // For free
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(int, posix_spawn_file_actions_destroy,
+ (posix_spawn_file_actions_t * actions)) {
+ if (actions == nullptr)
+ return EINVAL;
+ if (actions->__front == nullptr)
+ return 0;
+
+ auto *act = reinterpret_cast<BaseSpawnFileAction *>(actions->__front);
+ actions->__front = nullptr;
+ actions->__back = nullptr;
+
+ while (act != nullptr) {
+ auto *next = act->next;
+ free(act);
+ act = next;
+ }
+
+ return 0;
+}
+
+} // namespace __llvm_libc
--- /dev/null
+//===-- Impl header for posix_spawn_file_actions_destroy --------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SPAWN_POSIX_SPAWN_FILE_ACTIONS_DESTROY_H
+#define LLVM_LIBC_SRC_SPAWN_POSIX_SPAWN_FILE_ACTIONS_DESTROY_H
+
+#include <spawn.h>
+
+namespace __llvm_libc {
+
+int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *actions);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_SPAWN_POSIX_SPAWN_FILE_ACTIONS_DESTROY_H
--- /dev/null
+//===-- Implementation of posix_spawn_file_actions_init -------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "posix_spawn_file_actions_init.h"
+
+#include "src/__support/common.h"
+
+#include <spawn.h>
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(int, posix_spawn_file_actions_init,
+ (posix_spawn_file_actions_t * actions)) {
+ actions->__front = nullptr;
+ actions->__back = nullptr;
+ return 0;
+}
+
+} // namespace __llvm_libc
--- /dev/null
+//===-- Implementation header for posix_spawn_file_actions_init -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SPAWN_POSIX_SPAWN_FILE_ACTIONS_INIT_H
+#define LLVM_LIBC_SRC_SPAWN_POSIX_SPAWN_FILE_ACTIONS_INIT_H
+
+#include <spawn.h>
+
+namespace __llvm_libc {
+
+int posix_spawn_file_actions_init(posix_spawn_file_actions_t *actions);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_SPAWN_POSIX_SPAWN_FILE_ACTIONS_INIT_H
# since assert uses the signal API, we disable assert also.
# add_subdirectory(assert)
add_subdirectory(signal)
+add_subdirectory(spawn)
add_subdirectory(time)
if(${LIBC_TARGET_OS} STREQUAL "linux")
--- /dev/null
+add_libc_testsuite(libc_spawn_unittests)
+
+add_libc_unittest(
+ posix_spawn_file_actions_test
+ SUITE
+ libc_spawn_unittests
+ SRCS
+ posix_spawn_file_actions_test.cpp
+ DEPENDS
+ libc.include.errno
+ libc.include.spawn
+ libc.src.spawn.file_actions
+ libc.src.spawn.posix_spawn_file_actions_addclose
+ libc.src.spawn.posix_spawn_file_actions_adddup2
+ libc.src.spawn.posix_spawn_file_actions_addopen
+ libc.src.spawn.posix_spawn_file_actions_destroy
+ libc.src.spawn.posix_spawn_file_actions_init
+)
--- /dev/null
+//===-- Unittests for posix_spwan_file_actions_t manipulation -------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/spawn/file_actions.h"
+#include "src/spawn/posix_spawn_file_actions_addclose.h"
+#include "src/spawn/posix_spawn_file_actions_adddup2.h"
+#include "src/spawn/posix_spawn_file_actions_addopen.h"
+#include "src/spawn/posix_spawn_file_actions_destroy.h"
+#include "src/spawn/posix_spawn_file_actions_init.h"
+#include "utils/UnitTest/Test.h"
+
+#include <errno.h>
+#include <spawn.h>
+#include <stdint.h>
+
+TEST(LlvmLibcPosixSpawnFileActionsTest, AddActions) {
+ posix_spawn_file_actions_t actions;
+ ASSERT_EQ(__llvm_libc::posix_spawn_file_actions_init(&actions), 0);
+
+ ASSERT_EQ(uintptr_t(actions.__front), uintptr_t(nullptr));
+ ASSERT_EQ(uintptr_t(actions.__back), uintptr_t(nullptr));
+
+ ASSERT_EQ(__llvm_libc::posix_spawn_file_actions_addclose(&actions, 10), 0);
+ ASSERT_NE(uintptr_t(actions.__front), uintptr_t(nullptr));
+ ASSERT_NE(uintptr_t(actions.__back), uintptr_t(nullptr));
+
+ ASSERT_EQ(__llvm_libc::posix_spawn_file_actions_adddup2(&actions, 11, 12), 0);
+ ASSERT_EQ(__llvm_libc::posix_spawn_file_actions_addopen(&actions, 13,
+ "path/to/file", 0, 0),
+ 0);
+
+ __llvm_libc::BaseSpawnFileAction *act =
+ reinterpret_cast<__llvm_libc::BaseSpawnFileAction *>(actions.__front);
+ int action_count = 0;
+ while (act != nullptr) {
+ ++action_count;
+ if (action_count == 1)
+ ASSERT_EQ(act->type, __llvm_libc::BaseSpawnFileAction::CLOSE);
+ if (action_count == 2)
+ ASSERT_EQ(act->type, __llvm_libc::BaseSpawnFileAction::DUP2);
+ if (action_count == 3)
+ ASSERT_EQ(act->type, __llvm_libc::BaseSpawnFileAction::OPEN);
+ act = act->next;
+ }
+ ASSERT_EQ(action_count, 3);
+ ASSERT_EQ(__llvm_libc::posix_spawn_file_actions_destroy(&actions), 0);
+}
+
+TEST(LlvmLibcPosixSpawnFileActionsTest, InvalidActions) {
+ ASSERT_EQ(__llvm_libc::posix_spawn_file_actions_addclose(nullptr, 1), EINVAL);
+ ASSERT_EQ(__llvm_libc::posix_spawn_file_actions_adddup2(nullptr, 1, 2),
+ EINVAL);
+ ASSERT_EQ(
+ __llvm_libc::posix_spawn_file_actions_addopen(nullptr, 1, nullptr, 0, 0),
+ EINVAL);
+ ASSERT_EQ(__llvm_libc::posix_spawn_file_actions_destroy(nullptr), EINVAL);
+
+ posix_spawn_file_actions_t actions;
+ ASSERT_EQ(__llvm_libc::posix_spawn_file_actions_init(&actions), 0);
+ ASSERT_EQ(__llvm_libc::posix_spawn_file_actions_addclose(&actions, -1),
+ EBADF);
+ ASSERT_EQ(__llvm_libc::posix_spawn_file_actions_adddup2(&actions, -1, 2),
+ EBADF);
+ ASSERT_EQ(__llvm_libc::posix_spawn_file_actions_adddup2(&actions, 1, -2),
+ EBADF);
+ ASSERT_EQ(__llvm_libc::posix_spawn_file_actions_addopen(&actions, -1, nullptr,
+ 0, 0),
+ EBADF);
+ ASSERT_EQ(__llvm_libc::posix_spawn_file_actions_destroy(&actions), 0);
+}