diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index bb4973628d58..4103ee0331a2 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -251,6 +251,9 @@ set(TARGET_LIBC_ENTRYPOINTS # sys/ioctl.h entrypoints libc.src.sys.ioctl.ioctl + # sys/ipc.h entrypoints + libc.src.sys.ipc.ftok + # sys/mman.h entrypoints libc.src.sys.mman.madvise libc.src.sys.mman.mincore diff --git a/libc/config/linux/x86_64/headers.txt b/libc/config/linux/x86_64/headers.txt index d0f62eb104dc..0669cc30aead 100644 --- a/libc/config/linux/x86_64/headers.txt +++ b/libc/config/linux/x86_64/headers.txt @@ -38,6 +38,7 @@ set(TARGET_PUBLIC_HEADERS libc.include.sys_auxv libc.include.sys_epoll libc.include.sys_ioctl + libc.include.sys_ipc libc.include.sys_mman libc.include.sys_prctl libc.include.sys_queue diff --git a/libc/hdr/types/CMakeLists.txt b/libc/hdr/types/CMakeLists.txt index 3385fe81fe22..03e7066f83a0 100644 --- a/libc/hdr/types/CMakeLists.txt +++ b/libc/hdr/types/CMakeLists.txt @@ -233,6 +233,15 @@ add_proxy_header_library( libc.include.sys_time ) +add_proxy_header_library( + key_t + HDRS + key_t.h + FULL_BUILD_DEPENDS + libc.include.llvm-libc-types.key_t + libc.include.sys_ipc +) + add_proxy_header_library( pid_t HDRS diff --git a/libc/hdr/types/key_t.h b/libc/hdr/types/key_t.h new file mode 100644 index 000000000000..478522a93a19 --- /dev/null +++ b/libc/hdr/types/key_t.h @@ -0,0 +1,22 @@ +//===-- Proxy for key_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_HDR_TYPES_KEY_T_H +#define LLVM_LIBC_HDR_TYPES_KEY_T_H + +#ifdef LIBC_FULL_BUILD + +#include "include/llvm-libc-types/key_t.h" + +#else // Overlay mode + +#include + +#endif // LLVM_LIBC_FULL_BUILD + +#endif // LLVM_LIBC_HDR_TYPES_KEY_T_H diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt index c6254aafe384..5ffee68b5feb 100644 --- a/libc/include/CMakeLists.txt +++ b/libc/include/CMakeLists.txt @@ -557,6 +557,20 @@ add_header_macro( .llvm-libc-macros.sys_ioctl_macros ) +add_header_macro( + sys_ipc + ../libc/include/sys/ipc.yaml + sys/ipc.h + DEPENDS + .llvm_libc_common_h + .llvm-libc-macros.sys_ipc_macros + .llvm-libc-types.key_t + .llvm-libc-types.uid_t + .llvm-libc-types.gid_t + .llvm-libc-types.mode_t + .llvm-libc-types.struct_ipc_perm +) + add_header_macro( sys_mman ../libc/include/sys/mman.yaml @@ -708,6 +722,7 @@ add_header_macro( .llvm-libc-types.dev_t .llvm-libc-types.gid_t .llvm-libc-types.ino_t + .llvm-libc-types.key_t .llvm-libc-types.mode_t .llvm-libc-types.nlink_t .llvm-libc-types.off_t diff --git a/libc/include/llvm-libc-macros/CMakeLists.txt b/libc/include/llvm-libc-macros/CMakeLists.txt index b16337cccd58..553879e27d3d 100644 --- a/libc/include/llvm-libc-macros/CMakeLists.txt +++ b/libc/include/llvm-libc-macros/CMakeLists.txt @@ -226,6 +226,12 @@ add_macro_header( sys-ioctl-macros.h ) +add_macro_header( + sys_ipc_macros + HDR + sys-ipc-macros.h +) + add_macro_header( sys_stat_macros HDR diff --git a/libc/include/llvm-libc-macros/linux/CMakeLists.txt b/libc/include/llvm-libc-macros/linux/CMakeLists.txt index 61da55eabd40..60376641b50f 100644 --- a/libc/include/llvm-libc-macros/linux/CMakeLists.txt +++ b/libc/include/llvm-libc-macros/linux/CMakeLists.txt @@ -34,6 +34,12 @@ add_header( sys-ioctl-macros.h ) +add_header( + sys_ipc_macros + HDR + sys-ipc-macros.h +) + add_header( sys_random_macros HDR diff --git a/libc/include/llvm-libc-macros/linux/sys-ipc-macros.h b/libc/include/llvm-libc-macros/linux/sys-ipc-macros.h new file mode 100644 index 000000000000..87546ac314d8 --- /dev/null +++ b/libc/include/llvm-libc-macros/linux/sys-ipc-macros.h @@ -0,0 +1,24 @@ +//===-- Definition of macros from sys/ipc.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_MACROS_LINUX_SYS_IPC_MACROS_H +#define LLVM_LIBC_MACROS_LINUX_SYS_IPC_MACROS_H + +#define IPC_PRIVATE 0 + +// Resource get request flags. +#define IPC_CREAT 01000 +#define IPC_EXCL 02000 +#define IPC_NOWAIT 04000 + +// Control commands used with semctl, msgctl, and shmctl. +#define IPC_RMID 0 +#define IPC_SET 1 +#define IPC_STAT 2 + +#endif // LLVM_LIBC_MACROS_LINUX_SYS_IPC_MACROS_H diff --git a/libc/include/llvm-libc-macros/sys-ipc-macros.h b/libc/include/llvm-libc-macros/sys-ipc-macros.h new file mode 100644 index 000000000000..37e7e45456d2 --- /dev/null +++ b/libc/include/llvm-libc-macros/sys-ipc-macros.h @@ -0,0 +1,16 @@ +//===-- Macros defined in sys/ipc.h header file ---------------------------===// +// +// 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_MACROS_SYS_IPC_MACROS_H +#define LLVM_LIBC_MACROS_SYS_IPC_MACROS_H + +#ifdef __linux__ +#include "linux/sys-ipc-macros.h" +#endif + +#endif // LLVM_LIBC_MACROS_SYS_IPC_MACROS_H diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt index dc36dfeadba5..eb8356cbfb8b 100644 --- a/libc/include/llvm-libc-types/CMakeLists.txt +++ b/libc/include/llvm-libc-types/CMakeLists.txt @@ -42,6 +42,7 @@ add_header(imaxdiv_t HDR imaxdiv_t.h) add_header(in_addr_t HDR in_addr_t.h) add_header(in_addr HDR in_addr.h DEPENDS .in_addr_t) add_header(ino_t HDR ino_t.h) +add_header(key_t HDR key_t.h) add_header(mbstate_t HDR mbstate_t.h) add_header(mode_t HDR mode_t.h) add_header(mtx_t HDR mtx_t.h DEPENDS .__futex_word .__mutex_type) @@ -79,6 +80,15 @@ add_header(dl_info HDR Dl_info.h) add_header(struct_f_owner_ex HDR struct_f_owner_ex.h DEPENDS .pid_t) add_header(struct_flock HDR struct_flock.h DEPENDS .off_t .pid_t) add_header(struct_flock64 HDR struct_flock64.h DEPENDS .off64_t .pid_t) +add_header( + struct_ipc_perm + HDR struct_ipc_perm.h + DEPENDS + .key_t + .uid_t + .gid_t + .mode_t +) add_header(struct_pollfd HDR struct_pollfd.h) add_header(struct_rlimit HDR struct_rlimit.h DEPENDS .rlim_t) add_header(struct_sched_param HDR struct_sched_param.h) diff --git a/libc/include/llvm-libc-types/key_t.h b/libc/include/llvm-libc-types/key_t.h new file mode 100644 index 000000000000..151546988086 --- /dev/null +++ b/libc/include/llvm-libc-types/key_t.h @@ -0,0 +1,14 @@ +//===-- Definition of key_t type ------------------------------------------===// +// +// 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_KEY_T_H +#define LLVM_LIBC_TYPES_KEY_T_H + +typedef __INT32_TYPE__ key_t; + +#endif // LLVM_LIBC_TYPES_KEY_T_H diff --git a/libc/include/llvm-libc-types/struct_ipc_perm.h b/libc/include/llvm-libc-types/struct_ipc_perm.h new file mode 100644 index 000000000000..5dc1c12427a4 --- /dev/null +++ b/libc/include/llvm-libc-types/struct_ipc_perm.h @@ -0,0 +1,34 @@ +//===-- Definition of struct ipc_perm -------------------------------------===// +// +// 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_STRUCT_IPC_PERM_H +#define LLVM_LIBC_TYPES_STRUCT_IPC_PERM_H + +#include "gid_t.h" +#include "key_t.h" +#include "mode_t.h" +#include "uid_t.h" + +#ifdef __linux__ +struct ipc_perm { + key_t __key; + uid_t uid; + gid_t gid; + uid_t cuid; + gid_t cgid; + mode_t mode; + unsigned short __seq; + unsigned short __padding; + unsigned long __unused_0; + unsigned long __unused_1; +}; +#else +#error "ipc_perm not defined for the target platform" +#endif + +#endif // LLVM_LIBC_TYPES_STRUCT_IPC_PERM_H diff --git a/libc/include/sys/ipc.yaml b/libc/include/sys/ipc.yaml new file mode 100644 index 000000000000..77593af1dc0a --- /dev/null +++ b/libc/include/sys/ipc.yaml @@ -0,0 +1,51 @@ +header: sys/ipc.h +standards: + - posix + - linux +macros: + - macro_name: IPC_PRIVATE + macro_header: sys-ipc-macros.h + standards: + - posix + - macro_name: IPC_CREAT + macro_header: sys-ipc-macros.h + standards: + - posix + - macro_name: IPC_EXCL + macro_header: sys-ipc-macros.h + standards: + - posix + - macro_name: IPC_NOWAIT + macro_header: sys-ipc-macros.h + standards: + - posix + - macro_name: IPC_RMID + macro_header: sys-ipc-macros.h + standards: + - posix + - macro_name: IPC_SET + macro_header: sys-ipc-macros.h + standards: + - posix + - macro_name: IPC_STAT + macro_header: sys-ipc-macros.h + standards: + - posix + - macro_name: IPC_INFO + macro_header: sys-ipc-macros.h + standards: + - linux +types: + - type_name: key_t + - type_name: uid_t + - type_name: gid_t + - type_name: mode_t + - type_name: struct_ipc_perm +functions: + - name: ftok + standards: + - posix + return_type: key_t + arguments: + - type: const char * + - type: int diff --git a/libc/include/sys/types.yaml b/libc/include/sys/types.yaml index a00429d3817e..126c597b3035 100644 --- a/libc/include/sys/types.yaml +++ b/libc/include/sys/types.yaml @@ -8,6 +8,7 @@ types: - type_name: dev_t - type_name: gid_t - type_name: ino_t + - type_name: key_t - type_name: mode_t - type_name: nlink_t - type_name: off_t diff --git a/libc/src/sys/CMakeLists.txt b/libc/src/sys/CMakeLists.txt index 0fa11e9eee69..1c17ec31a859 100644 --- a/libc/src/sys/CMakeLists.txt +++ b/libc/src/sys/CMakeLists.txt @@ -1,5 +1,6 @@ add_subdirectory(auxv) add_subdirectory(epoll) +add_subdirectory(ipc) add_subdirectory(mman) add_subdirectory(random) add_subdirectory(resource) diff --git a/libc/src/sys/ipc/CMakeLists.txt b/libc/src/sys/ipc/CMakeLists.txt new file mode 100644 index 000000000000..e20ac7e3f964 --- /dev/null +++ b/libc/src/sys/ipc/CMakeLists.txt @@ -0,0 +1,10 @@ +if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS}) + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS}) +endif() + +add_entrypoint_object( + ftok + ALIAS + DEPENDS + .${LIBC_TARGET_OS}.ftok +) diff --git a/libc/src/sys/ipc/ftok.h b/libc/src/sys/ipc/ftok.h new file mode 100644 index 000000000000..24603e626c08 --- /dev/null +++ b/libc/src/sys/ipc/ftok.h @@ -0,0 +1,21 @@ +//===-- Implementation header for ftok --------------------------*- 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_SYS_IPC_FTOK_H +#define LLVM_LIBC_SRC_SYS_IPC_FTOK_H + +#include "hdr/types/key_t.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +key_t ftok(const char *path, int id); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_SYS_IPC_FTOK_H diff --git a/libc/src/sys/ipc/linux/CMakeLists.txt b/libc/src/sys/ipc/linux/CMakeLists.txt new file mode 100644 index 000000000000..d5b2d1b8ab77 --- /dev/null +++ b/libc/src/sys/ipc/linux/CMakeLists.txt @@ -0,0 +1,23 @@ +add_header_library( + kernel_statx + HDRS + kernel_statx.h + DEPENDS + libc.hdr.fcntl_macros + libc.include.sys_syscall + libc.src.__support.error_or + libc.src.__support.OSUtil.osutil +) + +add_entrypoint_object( + ftok + SRCS + ftok.cpp + HDRS + ../ftok.h + DEPENDS + .kernel_statx + libc.hdr.types.key_t + libc.src.__support.common + libc.src.errno.errno +) diff --git a/libc/src/sys/ipc/linux/ftok.cpp b/libc/src/sys/ipc/linux/ftok.cpp new file mode 100644 index 000000000000..28762ac6e33f --- /dev/null +++ b/libc/src/sys/ipc/linux/ftok.cpp @@ -0,0 +1,38 @@ +//===-- Linux implementation of ftok --------------------------------------===// +// +// 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/sys/ipc/ftok.h" + +#include "src/__support/common.h" +#include "src/__support/error_or.h" +#include "src/__support/libc_errno.h" + +#include "kernel_statx.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(key_t, ftok, (const char *path, int id)) { + struct statx xbuf; + + ErrorOr err = statx_for_ftok(path, xbuf); + + if (!err.has_value()) { + libc_errno = err.error(); + return -1; + } + + // key layout based on user input and file stats metadata + // 31 24 16 0 + // +-------------+---------------+--------------+ + // user input id + minor dev num + file inode num + return static_cast( + ((id & 0xff) << 24) | + ((static_cast(xbuf.stx_dev_minor) & 0xff) << 16) | + (static_cast(xbuf.stx_ino) & 0xffff)); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/sys/ipc/linux/kernel_statx.h b/libc/src/sys/ipc/linux/kernel_statx.h new file mode 100644 index 000000000000..7613e1b50f20 --- /dev/null +++ b/libc/src/sys/ipc/linux/kernel_statx.h @@ -0,0 +1,34 @@ +//===-- Wrapper over SYS_statx syscall for ftok ---------------------------===// +// +// 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_SYS_IPC_LINUX_KERNEL_STATX_H +#define LLVM_LIBC_SRC_SYS_IPC_LINUX_KERNEL_STATX_H + +#include "hdr/fcntl_macros.h" +#include "src/__support/OSUtil/syscall.h" +#include "src/__support/error_or.h" +#include "sys/syscall.h" + +#include + +namespace LIBC_NAMESPACE_DECL { + +LIBC_INLINE ErrorOr statx_for_ftok(const char *path, struct statx &xbuf) { + + // store the file stats metadata into xbuf + int ret = LIBC_NAMESPACE::syscall_impl(SYS_statx, AT_FDCWD, path, 0, + STATX_BASIC_STATS, &xbuf); + + if (ret < 0) + return Error(-ret); + return 0; +} + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_SYS_IPC_LINUX_KERNEL_STATX_H diff --git a/libc/test/src/sys/CMakeLists.txt b/libc/test/src/sys/CMakeLists.txt index 13bf91eef04b..3b5ea64fb144 100644 --- a/libc/test/src/sys/CMakeLists.txt +++ b/libc/test/src/sys/CMakeLists.txt @@ -11,6 +11,7 @@ add_subdirectory(wait) add_subdirectory(prctl) add_subdirectory(auxv) add_subdirectory(epoll) +add_subdirectory(ipc) add_subdirectory(uio) add_subdirectory(time) add_subdirectory(ioctl) diff --git a/libc/test/src/sys/ipc/CMakeLists.txt b/libc/test/src/sys/ipc/CMakeLists.txt new file mode 100644 index 000000000000..b4bbe81c92ff --- /dev/null +++ b/libc/test/src/sys/ipc/CMakeLists.txt @@ -0,0 +1,3 @@ +if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS}) + add_subdirectory(${LIBC_TARGET_OS}) +endif() diff --git a/libc/test/src/sys/ipc/linux/CMakeLists.txt b/libc/test/src/sys/ipc/linux/CMakeLists.txt new file mode 100644 index 000000000000..21d501a3029e --- /dev/null +++ b/libc/test/src/sys/ipc/linux/CMakeLists.txt @@ -0,0 +1,19 @@ +add_custom_target(libc_sys_ipc_unittests) + +add_libc_unittest( + ftok_test + SUITE + libc_sys_ipc_unittests + SRCS + ftok_test.cpp + DEPENDS + libc.hdr.fcntl_macros + libc.include.sys_ipc + libc.src.errno.errno + libc.src.fcntl.open + libc.src.sys.ipc.ftok + libc.src.unistd.close + libc.src.unistd.unlink + libc.test.UnitTest.ErrnoCheckingTest + libc.test.UnitTest.ErrnoSetterMatcher +) diff --git a/libc/test/src/sys/ipc/linux/ftok_test.cpp b/libc/test/src/sys/ipc/linux/ftok_test.cpp new file mode 100644 index 000000000000..dd9a4702d439 --- /dev/null +++ b/libc/test/src/sys/ipc/linux/ftok_test.cpp @@ -0,0 +1,59 @@ +//===-- Unittests for ftok ------------------------------------------------===// +// +// 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/fcntl/open.h" +#include "src/sys/ipc/ftok.h" +#include "src/unistd/close.h" +#include "src/unistd/unlink.h" +#include "test/UnitTest/ErrnoCheckingTest.h" +#include "test/UnitTest/ErrnoSetterMatcher.h" +#include "test/UnitTest/Test.h" + +#include "hdr/fcntl_macros.h" + +using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher; +using LlvmLibcFtokTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest; + +TEST_F(LlvmLibcFtokTest, InvalidPath) { + ASSERT_THAT(LIBC_NAMESPACE::ftok("no/such/path", 1), Fails(ENOENT)); +} + +TEST_F(LlvmLibcFtokTest, DeterministicForPathAndId) { + // create a file + constexpr const char *TEST_FILE_NAME = "ftok.test"; + auto TEST_FILE = libc_make_test_file_path(TEST_FILE_NAME); + + // we first ensure such file exist and set to readable, writable + int fd = LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_WRONLY, 0600); + ASSERT_GT(fd, -1); + ASSERT_ERRNO_SUCCESS(); + ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0)); + + // create keys based on file path and user specified int + key_t key1 = LIBC_NAMESPACE::ftok(TEST_FILE, 'A'); + ASSERT_NE(key1, key_t(-1)); + ASSERT_ERRNO_SUCCESS(); + + key_t key2 = LIBC_NAMESPACE::ftok(TEST_FILE, 'A'); + ASSERT_NE(key2, key_t(-1)); + ASSERT_ERRNO_SUCCESS(); + + // key should be identical if both inputs are the same + ASSERT_EQ(key1, key2); + + // create another key + key_t key3 = LIBC_NAMESPACE::ftok(TEST_FILE, 'B'); + ASSERT_NE(key3, key_t(-1)); + ASSERT_ERRNO_SUCCESS(); + + // key should be different if any input is different + ASSERT_NE(key1, key3); + + // delete the file + ASSERT_THAT(LIBC_NAMESPACE::unlink(TEST_FILE), Succeeds(0)); +}