diff --git a/libc/config/linux/api.td b/libc/config/linux/api.td --- a/libc/config/linux/api.td +++ b/libc/config/linux/api.td @@ -289,3 +289,7 @@ def SysUtsNameAPI : PublicAPI<"sys/utsname.h"> { let Types = ["struct utsname"]; } + +def SpawnAPI : PublicAPI<"spawn.h"> { + let Types = ["mode_t", "posix_spawn_file_actions_t"]; +} diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -390,6 +390,13 @@ 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 diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt --- a/libc/include/CMakeLists.txt +++ b/libc/include/CMakeLists.txt @@ -213,6 +213,16 @@ .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. diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt --- a/libc/include/llvm-libc-types/CMakeLists.txt +++ b/libc/include/llvm-libc-types/CMakeLists.txt @@ -39,6 +39,7 @@ 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) diff --git a/libc/include/llvm-libc-types/posix_spawn_file_actions_t.h b/libc/include/llvm-libc-types/posix_spawn_file_actions_t.h new file mode 100644 --- /dev/null +++ b/libc/include/llvm-libc-types/posix_spawn_file_actions_t.h @@ -0,0 +1,17 @@ +//===-- 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 diff --git a/libc/include/spawn.h.def b/libc/include/spawn.h.def new file mode 100644 --- /dev/null +++ b/libc/include/spawn.h.def @@ -0,0 +1,16 @@ +//===-- 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 diff --git a/libc/spec/posix.td b/libc/spec/posix.td --- a/libc/spec/posix.td +++ b/libc/spec/posix.td @@ -50,6 +50,10 @@ def AtForkCallbackT : NamedType<"__atfork_callback_t">; +def PosixSpawnFileActionsT : NamedType<"posix_spawn_file_actions_t">; +def PosixSpawnFileActionsTPtr : PtrType; +def PosixSpawnFileActionsTRestrictedPtr : RestrictedPtrType; + def POSIX : StandardSpec<"POSIX"> { PtrType CharPtr = PtrType; RestrictedPtrType RestrictedCharPtr = RestrictedPtrType; @@ -1045,6 +1049,41 @@ [] // Functions >; + HeaderSpec Spawn = HeaderSpec< + "spawn.h", + [], // Macros + [PosixSpawnFileActionsT, ModeTType], + [], // Enumerations + [ + FunctionSpec< + "posix_spawn_file_actions_addclose", + RetValSpec, + [ArgSpec, ArgSpec] + >, + FunctionSpec< + "posix_spawn_file_actions_adddup2", + RetValSpec, + [ArgSpec, ArgSpec, ArgSpec] + >, + FunctionSpec< + "posix_spawn_file_actions_addopen", + RetValSpec, + [ArgSpec, ArgSpec, + ArgSpec, ArgSpec, ArgSpec] + >, + FunctionSpec< + "posix_spawn_file_actions_destroy", + RetValSpec, + [ArgSpec] + >, + FunctionSpec< + "posix_spawn_file_actions_init", + RetValSpec, + [ArgSpec] + >, + ] + >; + let Headers = [ CType, Dirent, @@ -1052,6 +1091,7 @@ FCntl, PThread, Signal, + Spawn, StdIO, StdLib, SysIOctl, diff --git a/libc/src/CMakeLists.txt b/libc/src/CMakeLists.txt --- a/libc/src/CMakeLists.txt +++ b/libc/src/CMakeLists.txt @@ -26,5 +26,6 @@ # 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) diff --git a/libc/src/spawn/CMakeLists.txt b/libc/src/spawn/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/libc/src/spawn/CMakeLists.txt @@ -0,0 +1,65 @@ +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 +) diff --git a/libc/src/spawn/file_actions.h b/libc/src/spawn/file_actions.h new file mode 100644 --- /dev/null +++ b/libc/src/spawn/file_actions.h @@ -0,0 +1,58 @@ +//===-- 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 // For mode_t +#include + +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(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 diff --git a/libc/src/spawn/posix_spawn_file_actions_addclose.h b/libc/src/spawn/posix_spawn_file_actions_addclose.h new file mode 100644 --- /dev/null +++ b/libc/src/spawn/posix_spawn_file_actions_addclose.h @@ -0,0 +1,21 @@ +//===-- 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 + +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 diff --git a/libc/src/spawn/posix_spawn_file_actions_addclose.cpp b/libc/src/spawn/posix_spawn_file_actions_addclose.cpp new file mode 100644 --- /dev/null +++ b/libc/src/spawn/posix_spawn_file_actions_addclose.cpp @@ -0,0 +1,38 @@ +//===-- 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 +#include +#include // 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( + 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 diff --git a/libc/src/spawn/posix_spawn_file_actions_adddup2.h b/libc/src/spawn/posix_spawn_file_actions_adddup2.h new file mode 100644 --- /dev/null +++ b/libc/src/spawn/posix_spawn_file_actions_adddup2.h @@ -0,0 +1,21 @@ +//===-- 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 + +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 diff --git a/libc/src/spawn/posix_spawn_file_actions_adddup2.cpp b/libc/src/spawn/posix_spawn_file_actions_adddup2.cpp new file mode 100644 --- /dev/null +++ b/libc/src/spawn/posix_spawn_file_actions_adddup2.cpp @@ -0,0 +1,40 @@ +//===-- 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 +#include +#include // 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( + 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 diff --git a/libc/src/spawn/posix_spawn_file_actions_addopen.h b/libc/src/spawn/posix_spawn_file_actions_addopen.h new file mode 100644 --- /dev/null +++ b/libc/src/spawn/posix_spawn_file_actions_addopen.h @@ -0,0 +1,22 @@ +//===-- 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 + +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 diff --git a/libc/src/spawn/posix_spawn_file_actions_addopen.cpp b/libc/src/spawn/posix_spawn_file_actions_addopen.cpp new file mode 100644 --- /dev/null +++ b/libc/src/spawn/posix_spawn_file_actions_addopen.cpp @@ -0,0 +1,43 @@ +//===-- 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 +#include +#include // 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( + 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 diff --git a/libc/src/spawn/posix_spawn_file_actions_destroy.h b/libc/src/spawn/posix_spawn_file_actions_destroy.h new file mode 100644 --- /dev/null +++ b/libc/src/spawn/posix_spawn_file_actions_destroy.h @@ -0,0 +1,20 @@ +//===-- 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 + +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 diff --git a/libc/src/spawn/posix_spawn_file_actions_destroy.cpp b/libc/src/spawn/posix_spawn_file_actions_destroy.cpp new file mode 100644 --- /dev/null +++ b/libc/src/spawn/posix_spawn_file_actions_destroy.cpp @@ -0,0 +1,40 @@ +//===-- 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 +#include +#include // 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(actions->__front); + actions->__front = nullptr; + actions->__back = nullptr; + + while (act != nullptr) { + auto *next = act->next; + free(act); + act = next; + } + + return 0; +} + +} // namespace __llvm_libc diff --git a/libc/src/spawn/posix_spawn_file_actions_init.h b/libc/src/spawn/posix_spawn_file_actions_init.h new file mode 100644 --- /dev/null +++ b/libc/src/spawn/posix_spawn_file_actions_init.h @@ -0,0 +1,20 @@ +//===-- 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 + +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 diff --git a/libc/src/spawn/posix_spawn_file_actions_init.cpp b/libc/src/spawn/posix_spawn_file_actions_init.cpp new file mode 100644 --- /dev/null +++ b/libc/src/spawn/posix_spawn_file_actions_init.cpp @@ -0,0 +1,24 @@ +//===-- 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 + +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 diff --git a/libc/test/src/CMakeLists.txt b/libc/test/src/CMakeLists.txt --- a/libc/test/src/CMakeLists.txt +++ b/libc/test/src/CMakeLists.txt @@ -52,6 +52,7 @@ # 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") diff --git a/libc/test/src/spawn/CMakeLists.txt b/libc/test/src/spawn/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/libc/test/src/spawn/CMakeLists.txt @@ -0,0 +1,18 @@ +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 +) diff --git a/libc/test/src/spawn/posix_spawn_file_actions_test.cpp b/libc/test/src/spawn/posix_spawn_file_actions_test.cpp new file mode 100644 --- /dev/null +++ b/libc/test/src/spawn/posix_spawn_file_actions_test.cpp @@ -0,0 +1,75 @@ +//===-- 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 +#include +#include + +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); +}