aboutsummaryrefslogtreecommitdiff
path: root/libc
diff options
context:
space:
mode:
Diffstat (limited to 'libc')
-rw-r--r--libc/config/baremetal/aarch64/entrypoints.txt1
-rw-r--r--libc/config/baremetal/arm/entrypoints.txt1
-rw-r--r--libc/config/linux/aarch64/entrypoints.txt2
-rw-r--r--libc/config/linux/riscv/entrypoints.txt1
-rw-r--r--libc/config/linux/x86_64/entrypoints.txt2
-rw-r--r--libc/docs/headers/time.rst4
-rw-r--r--libc/include/time.yaml7
-rw-r--r--libc/include/unistd.yaml8
-rw-r--r--libc/src/__support/time/CMakeLists.txt9
-rw-r--r--libc/src/__support/time/clock_settime.h22
-rw-r--r--libc/src/__support/time/linux/CMakeLists.txt15
-rw-r--r--libc/src/__support/time/linux/clock_settime.cpp53
-rw-r--r--libc/src/time/CMakeLists.txt8
-rw-r--r--libc/src/time/clock_settime.h22
-rw-r--r--libc/src/time/linux/CMakeLists.txt13
-rw-r--r--libc/src/time/linux/clock.cpp2
-rw-r--r--libc/src/time/linux/clock_gettime.cpp3
-rw-r--r--libc/src/time/linux/clock_settime.cpp30
-rw-r--r--libc/src/time/linux/nanosleep.cpp3
-rw-r--r--libc/src/time/linux/timespec_get.cpp2
-rw-r--r--libc/src/time/strftime.cpp4
-rw-r--r--libc/src/time/strftime_core/CMakeLists.txt1
-rw-r--r--libc/src/time/strftime_core/strftime_main.h10
-rw-r--r--libc/src/time/strftime_l.cpp4
-rw-r--r--libc/src/unistd/CMakeLists.txt7
-rw-r--r--libc/src/unistd/fchown.h22
-rw-r--r--libc/src/unistd/linux/CMakeLists.txt14
-rw-r--r--libc/src/unistd/linux/fchown.cpp31
-rw-r--r--libc/test/UnitTest/BazelFilePath.cpp4
-rw-r--r--libc/test/src/time/CMakeLists.txt15
-rw-r--r--libc/test/src/time/clock_settime_test.cpp54
-rw-r--r--libc/test/src/unistd/CMakeLists.txt20
-rw-r--r--libc/test/src/unistd/fchown_test.cpp50
33 files changed, 427 insertions, 17 deletions
diff --git a/libc/config/baremetal/aarch64/entrypoints.txt b/libc/config/baremetal/aarch64/entrypoints.txt
index 049adb34..c69ab3d 100644
--- a/libc/config/baremetal/aarch64/entrypoints.txt
+++ b/libc/config/baremetal/aarch64/entrypoints.txt
@@ -323,6 +323,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.acos
libc.src.math.acosf
libc.src.math.acoshf
+ libc.src.math.asin
libc.src.math.asinf
libc.src.math.asinhf
libc.src.math.atan2
diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt
index 2444ec5..c566f8a 100644
--- a/libc/config/baremetal/arm/entrypoints.txt
+++ b/libc/config/baremetal/arm/entrypoints.txt
@@ -326,6 +326,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.acos
libc.src.math.acosf
libc.src.math.acoshf
+ libc.src.math.asin
libc.src.math.asinf
libc.src.math.asinhf
libc.src.math.atan2
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index e0dd15b..4257186 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -327,6 +327,7 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.unistd.execve
libc.src.unistd.faccessat
libc.src.unistd.fchdir
+ libc.src.unistd.fchown
libc.src.unistd.fpathconf
libc.src.unistd.fsync
libc.src.unistd.ftruncate
@@ -1143,6 +1144,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.time.ctime_r
libc.src.time.clock
libc.src.time.clock_gettime
+ libc.src.time.clock_settime
libc.src.time.difftime
libc.src.time.gettimeofday
libc.src.time.gmtime
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 0d031d8..b62a46b 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -1273,6 +1273,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.time.ctime_r
libc.src.time.clock
libc.src.time.clock_gettime
+ libc.src.time.clock_settime
libc.src.time.difftime
libc.src.time.gettimeofday
libc.src.time.gmtime
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index a44e204..8a46a7a 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -334,6 +334,7 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.unistd.execve
libc.src.unistd.faccessat
libc.src.unistd.fchdir
+ libc.src.unistd.fchown
libc.src.unistd.fpathconf
libc.src.unistd.fsync
libc.src.unistd.ftruncate
@@ -1313,6 +1314,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.time.ctime_r
libc.src.time.clock
libc.src.time.clock_gettime
+ libc.src.time.clock_settime
libc.src.time.difftime
libc.src.time.gettimeofday
libc.src.time.gmtime
diff --git a/libc/docs/headers/time.rst b/libc/docs/headers/time.rst
index 55bc1a1..f07e0d9 100644
--- a/libc/docs/headers/time.rst
+++ b/libc/docs/headers/time.rst
@@ -67,11 +67,11 @@ Implementation Status
+---------------------+---------+---------+---------+-----------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| clock_getres | | | | | | | | | | | | | |
+---------------------+---------+---------+---------+-----------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
-| clock_gettime | |check| | |check| | | |check| | | | | | | | | | |
+| clock_gettime | |check| | |check| | | |check| | | | | | | | | |check| | |check| |
+---------------------+---------+---------+---------+-----------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| clock_nanosleep | | | | | | | | | | | | | |
+---------------------+---------+---------+---------+-----------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
-| clock_settime | | | | | | | | | | | | | |
+| clock_settime | |check| | |check| | | |check| | | | | | | | | | |
+---------------------+---------+---------+---------+-----------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| ctime | |check| | |check| | | |check| | | | | | | | | | |
+---------------------+---------+---------+---------+-----------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
diff --git a/libc/include/time.yaml b/libc/include/time.yaml
index 88e50d1..c2b8a1e 100644
--- a/libc/include/time.yaml
+++ b/libc/include/time.yaml
@@ -67,6 +67,13 @@ functions:
arguments:
- type: clockid_t
- type: struct timespec *
+ - name: clock_settime
+ standard:
+ - POSIX
+ return_type: int
+ arguments:
+ - type: clockid_t
+ - type: const struct timespec *
- name: difftime
standard:
- stdc
diff --git a/libc/include/unistd.yaml b/libc/include/unistd.yaml
index 0e5b22e..3f5e957 100644
--- a/libc/include/unistd.yaml
+++ b/libc/include/unistd.yaml
@@ -120,6 +120,14 @@ functions:
return_type: int
arguments:
- type: int
+ - name: fchown
+ standards:
+ - POSIX
+ return_type: int
+ arguments:
+ - type: int
+ - type: uid_t
+ - type: gid_t
- name: fork
standards:
- POSIX
diff --git a/libc/src/__support/time/CMakeLists.txt b/libc/src/__support/time/CMakeLists.txt
index 8247e79..3851037 100644
--- a/libc/src/__support/time/CMakeLists.txt
+++ b/libc/src/__support/time/CMakeLists.txt
@@ -19,3 +19,12 @@ add_object_library(
DEPENDS
libc.src.__support.time.${LIBC_TARGET_OS}.clock_gettime
)
+
+if(TARGET libc.src.__support.time.${LIBC_TARGET_OS}.clock_settime)
+ add_object_library(
+ clock_settime
+ ALIAS
+ DEPENDS
+ libc.src.__support.time.${LIBC_TARGET_OS}.clock_settime
+ )
+endif()
diff --git a/libc/src/__support/time/clock_settime.h b/libc/src/__support/time/clock_settime.h
new file mode 100644
index 0000000..d8d305c
--- /dev/null
+++ b/libc/src/__support/time/clock_settime.h
@@ -0,0 +1,22 @@
+//===--- clock_settime linux implementation ---------------------*- 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___SUPPORT_TIME_CLOCK_SETTIME_H
+#define LLVM_LIBC_SRC___SUPPORT_TIME_CLOCK_SETTIME_H
+
+#include "hdr/types/clockid_t.h"
+#include "hdr/types/struct_timespec.h"
+#include "src/__support/error_or.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace internal {
+ErrorOr<int> clock_settime(clockid_t clockid, const timespec *ts);
+} // namespace internal
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_TIME_CLOCK_SETTIME_H
diff --git a/libc/src/__support/time/linux/CMakeLists.txt b/libc/src/__support/time/linux/CMakeLists.txt
index 6fec7ee..4785295 100644
--- a/libc/src/__support/time/linux/CMakeLists.txt
+++ b/libc/src/__support/time/linux/CMakeLists.txt
@@ -14,6 +14,21 @@ add_object_library(
libc.src.__support.OSUtil.linux.vdso
)
+add_object_library(
+ clock_settime
+ HDRS
+ ../clock_settime.h
+ SRCS
+ clock_settime.cpp
+ DEPENDS
+ libc.include.sys_syscall
+ libc.hdr.types.struct_timespec
+ libc.hdr.types.clockid_t
+ libc.src.__support.common
+ libc.src.__support.error_or
+ libc.src.__support.OSUtil.osutil
+)
+
add_header_library(
clock_conversion
HDRS
diff --git a/libc/src/__support/time/linux/clock_settime.cpp b/libc/src/__support/time/linux/clock_settime.cpp
new file mode 100644
index 0000000..dd42610
--- /dev/null
+++ b/libc/src/__support/time/linux/clock_settime.cpp
@@ -0,0 +1,53 @@
+//===--- clock_settime linux implementation ---------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/time/clock_settime.h"
+#include "hdr/types/clockid_t.h"
+#include "hdr/types/struct_timespec.h"
+#include "src/__support/OSUtil/syscall.h"
+#include "src/__support/common.h"
+#include "src/__support/error_or.h"
+#include "src/__support/macros/config.h"
+#include <sys/syscall.h>
+
+#if defined(SYS_clock_settime64)
+#include <linux/time_types.h>
+#endif
+
+namespace LIBC_NAMESPACE_DECL {
+namespace internal {
+ErrorOr<int> clock_settime(clockid_t clockid, const timespec *ts) {
+ int ret;
+#if defined(SYS_clock_settime)
+ ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_clock_settime,
+ static_cast<long>(clockid),
+ reinterpret_cast<long>(ts));
+#elif defined(SYS_clock_settime64)
+ static_assert(
+ sizeof(time_t) == sizeof(int64_t),
+ "SYS_clock_settime64 requires struct timespec with 64-bit members.");
+
+ __kernel_timespec ts64{};
+
+ // Populate the 64-bit kernel structure from the user-provided timespec
+ ts64.tv_sec = static_cast<decltype(ts64.tv_sec)>(ts->tv_sec);
+ ts64.tv_nsec = static_cast<decltype(ts64.tv_nsec)>(ts->tv_nsec);
+
+ ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_clock_settime64,
+ static_cast<long>(clockid),
+ reinterpret_cast<long>(&ts64));
+#else
+#error "SYS_clock_settime and SYS_clock_settime64 syscalls not available."
+#endif
+ if (ret < 0)
+ return Error(-ret);
+ return ret;
+}
+
+} // namespace internal
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/time/CMakeLists.txt b/libc/src/time/CMakeLists.txt
index ec942e3..4d647c2 100644
--- a/libc/src/time/CMakeLists.txt
+++ b/libc/src/time/CMakeLists.txt
@@ -245,3 +245,11 @@ add_entrypoint_object(
DEPENDS
.${LIBC_TARGET_OS}.clock_getres
)
+
+add_entrypoint_object(
+ clock_settime
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.clock_settime
+)
+
diff --git a/libc/src/time/clock_settime.h b/libc/src/time/clock_settime.h
new file mode 100644
index 0000000..9321dd1
--- /dev/null
+++ b/libc/src/time/clock_settime.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for clock_settime function --------*- 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_TIME_CLOCK_SETTIME_H
+#define LLVM_LIBC_SRC_TIME_CLOCK_SETTIME_H
+
+#include "hdr/types/clockid_t.h"
+#include "hdr/types/struct_timespec.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int clock_settime(clockid_t clockid, const timespec *tp);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_TIME_CLOCK_SETTIME_H
diff --git a/libc/src/time/linux/CMakeLists.txt b/libc/src/time/linux/CMakeLists.txt
index a6ec7c7..6ea0459 100644
--- a/libc/src/time/linux/CMakeLists.txt
+++ b/libc/src/time/linux/CMakeLists.txt
@@ -55,6 +55,19 @@ add_entrypoint_object(
)
add_entrypoint_object(
+ clock_settime
+ SRCS
+ clock_settime.cpp
+ HDRS
+ ../clock_settime.h
+ DEPENDS
+ libc.hdr.types.clockid_t
+ libc.hdr.types.struct_timespec
+ libc.src.__support.time.clock_settime
+ libc.src.errno.errno
+)
+
+add_entrypoint_object(
gettimeofday
SRCS
gettimeofday.cpp
diff --git a/libc/src/time/linux/clock.cpp b/libc/src/time/linux/clock.cpp
index c38697c..c560bd1 100644
--- a/libc/src/time/linux/clock.cpp
+++ b/libc/src/time/linux/clock.cpp
@@ -19,7 +19,7 @@ namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(clock_t, clock, ()) {
using namespace time_units;
- struct timespec ts;
+ timespec ts;
auto result = internal::clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
if (!result.has_value()) {
libc_errno = result.error();
diff --git a/libc/src/time/linux/clock_gettime.cpp b/libc/src/time/linux/clock_gettime.cpp
index b3fcd2b..52ace2a 100644
--- a/libc/src/time/linux/clock_gettime.cpp
+++ b/libc/src/time/linux/clock_gettime.cpp
@@ -15,8 +15,7 @@
namespace LIBC_NAMESPACE_DECL {
// TODO(michaelrj): Move this into time/linux with the other syscalls.
-LLVM_LIBC_FUNCTION(int, clock_gettime,
- (clockid_t clockid, struct timespec *ts)) {
+LLVM_LIBC_FUNCTION(int, clock_gettime, (clockid_t clockid, timespec *ts)) {
auto result = internal::clock_gettime(clockid, ts);
// A negative return value indicates an error with the magnitude of the
diff --git a/libc/src/time/linux/clock_settime.cpp b/libc/src/time/linux/clock_settime.cpp
new file mode 100644
index 0000000..3c582cf
--- /dev/null
+++ b/libc/src/time/linux/clock_settime.cpp
@@ -0,0 +1,30 @@
+//===---------- Linux implementation of the POSIX clock_settime function --===//
+//
+// 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/time/clock_settime.h"
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/time/clock_settime.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, clock_settime,
+ (clockid_t clockid, const timespec *ts)) {
+ auto result = internal::clock_settime(clockid, ts);
+
+ // A negative return value indicates an error with the magnitude of the
+ // value being the error code.
+ if (!result.has_value()) {
+ libc_errno = result.error();
+ return -1;
+ }
+ return 0;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/time/linux/nanosleep.cpp b/libc/src/time/linux/nanosleep.cpp
index e5df158..a30b97d 100644
--- a/libc/src/time/linux/nanosleep.cpp
+++ b/libc/src/time/linux/nanosleep.cpp
@@ -18,8 +18,7 @@
namespace LIBC_NAMESPACE_DECL {
-LLVM_LIBC_FUNCTION(int, nanosleep,
- (const struct timespec *req, struct timespec *rem)) {
+LLVM_LIBC_FUNCTION(int, nanosleep, (const timespec *req, timespec *rem)) {
#if SYS_nanosleep
int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_nanosleep, req, rem);
#elif defined(SYS_clock_nanosleep_time64)
diff --git a/libc/src/time/linux/timespec_get.cpp b/libc/src/time/linux/timespec_get.cpp
index a4d4372..031cb9f 100644
--- a/libc/src/time/linux/timespec_get.cpp
+++ b/libc/src/time/linux/timespec_get.cpp
@@ -15,7 +15,7 @@
namespace LIBC_NAMESPACE_DECL {
-LLVM_LIBC_FUNCTION(int, timespec_get, (struct timespec * ts, int base)) {
+LLVM_LIBC_FUNCTION(int, timespec_get, (timespec * ts, int base)) {
clockid_t clockid;
switch (base) {
case TIME_UTC:
diff --git a/libc/src/time/strftime.cpp b/libc/src/time/strftime.cpp
index 89b7d9b..ff8c05a 100644
--- a/libc/src/time/strftime.cpp
+++ b/libc/src/time/strftime.cpp
@@ -23,10 +23,10 @@ LLVM_LIBC_FUNCTION(size_t, strftime,
printf_core::WriteMode::FILL_BUFF_AND_DROP_OVERFLOW>::value>
wb(buffer, (buffsz > 0 ? buffsz - 1 : 0));
printf_core::Writer writer(wb);
- int ret = strftime_core::strftime_main(&writer, format, timeptr);
+ auto ret = strftime_core::strftime_main(&writer, format, timeptr);
if (buffsz > 0) // if the buffsz is 0 the buffer may be a null pointer.
wb.buff[wb.buff_cur] = '\0';
- return (ret < 0 || static_cast<size_t>(ret) >= buffsz) ? 0 : ret;
+ return (!ret.has_value() || ret.value() >= buffsz) ? 0 : ret.value();
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/time/strftime_core/CMakeLists.txt b/libc/src/time/strftime_core/CMakeLists.txt
index 3ffd283..a9aa573c 100644
--- a/libc/src/time/strftime_core/CMakeLists.txt
+++ b/libc/src/time/strftime_core/CMakeLists.txt
@@ -43,6 +43,7 @@ add_header_library(
.core_structs
.parser
.converter
+ libc.src.__support.error_or
libc.src.stdio.printf_core.writer
libc.hdr.types.struct_tm
)
diff --git a/libc/src/time/strftime_core/strftime_main.h b/libc/src/time/strftime_core/strftime_main.h
index 2b136d8..855a441 100644
--- a/libc/src/time/strftime_core/strftime_main.h
+++ b/libc/src/time/strftime_core/strftime_main.h
@@ -10,6 +10,7 @@
#define LLVM_LIBC_SRC_STDIO_STRFTIME_CORE_STRFTIME_MAIN_H
#include "hdr/types/struct_tm.h"
+#include "src/__support/error_or.h"
#include "src/__support/macros/config.h"
#include "src/stdio/printf_core/writer.h"
#include "src/time/strftime_core/converter.h"
@@ -20,8 +21,8 @@ namespace LIBC_NAMESPACE_DECL {
namespace strftime_core {
template <printf_core::WriteMode write_mode>
-int strftime_main(printf_core::Writer<write_mode> *writer,
- const char *__restrict str, const tm *timeptr) {
+ErrorOr<size_t> strftime_main(printf_core::Writer<write_mode> *writer,
+ const char *__restrict str, const tm *timeptr) {
Parser parser(str);
int result = 0;
for (strftime_core::FormatSection cur_section = parser.get_next_section();
@@ -33,11 +34,10 @@ int strftime_main(printf_core::Writer<write_mode> *writer,
result = writer->write(cur_section.raw_string);
if (result < 0)
- return result;
+ return Error(-result);
}
- // TODO: Use ErrorOr<size_t>
- return static_cast<int>(writer->get_chars_written());
+ return writer->get_chars_written();
}
} // namespace strftime_core
diff --git a/libc/src/time/strftime_l.cpp b/libc/src/time/strftime_l.cpp
index 409f868..2ec9063 100644
--- a/libc/src/time/strftime_l.cpp
+++ b/libc/src/time/strftime_l.cpp
@@ -26,10 +26,10 @@ LLVM_LIBC_FUNCTION(size_t, strftime_l,
printf_core::WriteMode::FILL_BUFF_AND_DROP_OVERFLOW>::value>
wb(buffer, (buffsz > 0 ? buffsz - 1 : 0));
printf_core::Writer writer(wb);
- int ret = strftime_core::strftime_main(&writer, format, timeptr);
+ auto ret = strftime_core::strftime_main(&writer, format, timeptr);
if (buffsz > 0) // if the buffsz is 0 the buffer may be a null pointer.
wb.buff[wb.buff_cur] = '\0';
- return (ret < 0 || static_cast<size_t>(ret) >= buffsz) ? 0 : ret;
+ return (!ret.has_value() || ret.value() >= buffsz) ? 0 : ret.value();
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/unistd/CMakeLists.txt b/libc/src/unistd/CMakeLists.txt
index 337480c..b7444a4 100644
--- a/libc/src/unistd/CMakeLists.txt
+++ b/libc/src/unistd/CMakeLists.txt
@@ -77,6 +77,13 @@ add_entrypoint_object(
)
add_entrypoint_object(
+ fchown
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.fchown
+)
+
+add_entrypoint_object(
fork
ALIAS
DEPENDS
diff --git a/libc/src/unistd/fchown.h b/libc/src/unistd/fchown.h
new file mode 100644
index 0000000..9ea4442
--- /dev/null
+++ b/libc/src/unistd/fchown.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for fchown ------------------------*- 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_UNISTD_FCHOWN_H
+#define LLVM_LIBC_SRC_UNISTD_FCHOWN_H
+
+#include "hdr/types/gid_t.h"
+#include "hdr/types/uid_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int fchown(int fildes, uid_t owner, gid_t group);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_UNISTD_FCHOWN_H
diff --git a/libc/src/unistd/linux/CMakeLists.txt b/libc/src/unistd/linux/CMakeLists.txt
index c2dacc6..c45b6ef 100644
--- a/libc/src/unistd/linux/CMakeLists.txt
+++ b/libc/src/unistd/linux/CMakeLists.txt
@@ -121,6 +121,20 @@ add_entrypoint_object(
)
add_entrypoint_object(
+ fchown
+ SRCS
+ fchown.cpp
+ HDRS
+ ../fchown.h
+ DEPENDS
+ libc.hdr.types.uid_t
+ libc.hdr.types.gid_t
+ libc.include.sys_syscall
+ libc.src.__support.OSUtil.osutil
+ libc.src.errno.errno
+)
+
+add_entrypoint_object(
fork
SRCS
fork.cpp
diff --git a/libc/src/unistd/linux/fchown.cpp b/libc/src/unistd/linux/fchown.cpp
new file mode 100644
index 0000000..9cf3d13
--- /dev/null
+++ b/libc/src/unistd/linux/fchown.cpp
@@ -0,0 +1,31 @@
+//===-- Linux implementation of fchown ------------------------------------===//
+//
+// 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/unistd/fchown.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+
+#include "hdr/types/gid_t.h"
+#include "hdr/types/uid_t.h"
+#include "src/__support/libc_errno.h"
+#include "src/__support/macros/config.h"
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, fchown, (int fildes, uid_t owner, gid_t group)) {
+ int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_fchown, fildes, owner, group);
+ if (ret < 0) {
+ libc_errno = -ret;
+ return -1;
+ }
+ return 0;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/UnitTest/BazelFilePath.cpp b/libc/test/UnitTest/BazelFilePath.cpp
index ee5fcaa..7f9f42b 100644
--- a/libc/test/UnitTest/BazelFilePath.cpp
+++ b/libc/test/UnitTest/BazelFilePath.cpp
@@ -20,6 +20,10 @@ namespace testing {
CString libc_make_test_file_path_func(const char *file_name) {
// This is the path to the folder bazel wants the test outputs written to.
const char *UNDECLARED_OUTPUTS_PATH = getenv("TEST_UNDECLARED_OUTPUTS_DIR");
+ // Do something sensible if not run under bazel, otherwise this may segfault
+ // when constructing the string.
+ if (UNDECLARED_OUTPUTS_PATH == nullptr)
+ UNDECLARED_OUTPUTS_PATH = "";
return cpp::string(UNDECLARED_OUTPUTS_PATH) + file_name;
}
diff --git a/libc/test/src/time/CMakeLists.txt b/libc/test/src/time/CMakeLists.txt
index 03e5428..c8e113f 100644
--- a/libc/test/src/time/CMakeLists.txt
+++ b/libc/test/src/time/CMakeLists.txt
@@ -124,6 +124,21 @@ add_libc_test(
libc.src.time.clock_getres
)
+add_libc_test(
+ clock_settime_test
+ SUITE
+ libc_time_unittests
+ SRCS
+ clock_settime_test.cpp
+ DEPENDS
+ libc.src.time.clock_settime
+ libc.hdr.types.time_t
+ libc.hdr.types.struct_timespec
+ libc.hdr.time_macros
+ libc.hdr.errno_macros
+ libc.test.UnitTest.ErrnoCheckingTest
+)
+
add_libc_unittest(
difftime_test
SUITE
diff --git a/libc/test/src/time/clock_settime_test.cpp b/libc/test/src/time/clock_settime_test.cpp
new file mode 100644
index 0000000..ccbad9e
--- /dev/null
+++ b/libc/test/src/time/clock_settime_test.cpp
@@ -0,0 +1,54 @@
+//===-- Unittests for clock_settime ---------------------------------------===//
+//
+// 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 "hdr/time_macros.h"
+#include "hdr/types/struct_timespec.h"
+#include "src/time/clock_settime.h"
+#include "test/UnitTest/ErrnoCheckingTest.h"
+#include "test/UnitTest/Test.h"
+
+using LlvmLibcClockSetTime = LIBC_NAMESPACE::testing::ErrnoCheckingTest;
+
+#ifdef CLOCK_MONOTONIC
+TEST_F(LlvmLibcClockSetTime, MonotonicIsNotSettable) {
+ timespec ts = {0, 0};
+ int result = LIBC_NAMESPACE::clock_settime(CLOCK_MONOTONIC, &ts);
+ ASSERT_EQ(result, -1);
+ ASSERT_ERRNO_EQ(EINVAL);
+}
+#endif // CLOCK_MONOTONIC
+
+TEST_F(LlvmLibcClockSetTime, InvalidClockId) {
+ timespec ts = {0, 0};
+ int result = LIBC_NAMESPACE::clock_settime(static_cast<clockid_t>(-1), &ts);
+ ASSERT_EQ(result, -1);
+ ASSERT_ERRNO_EQ(EINVAL);
+}
+
+TEST_F(LlvmLibcClockSetTime, InvalidTimespecNsec) {
+ timespec ts = {0, 1000000000L};
+ int result = LIBC_NAMESPACE::clock_settime(CLOCK_REALTIME, &ts);
+ ASSERT_EQ(result, -1);
+ ASSERT_ERRNO_EQ(EINVAL);
+}
+
+TEST_F(LlvmLibcClockSetTime, NullPointerIsEFAULT) {
+ int result = LIBC_NAMESPACE::clock_settime(CLOCK_REALTIME, nullptr);
+ ASSERT_EQ(result, -1);
+ ASSERT_ERRNO_EQ(EFAULT);
+}
+
+TEST_F(LlvmLibcClockSetTime, ClockIsSet) {
+ timespec ts = {0, 0};
+ int result = LIBC_NAMESPACE::clock_settime(CLOCK_REALTIME, &ts);
+ if (result == 0) {
+ ASSERT_ERRNO_SUCCESS();
+ } else {
+ ASSERT_ERRNO_EQ(EPERM);
+ }
+}
diff --git a/libc/test/src/unistd/CMakeLists.txt b/libc/test/src/unistd/CMakeLists.txt
index 0707053..3012ea9 100644
--- a/libc/test/src/unistd/CMakeLists.txt
+++ b/libc/test/src/unistd/CMakeLists.txt
@@ -147,6 +147,26 @@ add_libc_unittest(
)
add_libc_unittest(
+ fchown_test
+ SUITE
+ libc_unistd_unittests
+ SRCS
+ fchown_test.cpp
+ DEPENDS
+ libc.hdr.fcntl_macros
+ libc.include.unistd
+ libc.src.errno.errno
+ libc.src.unistd.fchown
+ libc.src.unistd.close
+ libc.src.unistd.unlink
+ libc.src.fcntl.open
+ libc.src.unistd.getuid
+ libc.src.unistd.getgid
+ libc.test.UnitTest.ErrnoCheckingTest
+ libc.test.UnitTest.ErrnoSetterMatcher
+)
+
+add_libc_unittest(
ftruncate_test
SUITE
libc_unistd_unittests
diff --git a/libc/test/src/unistd/fchown_test.cpp b/libc/test/src/unistd/fchown_test.cpp
new file mode 100644
index 0000000..7954410
--- /dev/null
+++ b/libc/test/src/unistd/fchown_test.cpp
@@ -0,0 +1,50 @@
+//===-- Unittests for fchown ----------------------------------------------===//
+//
+// 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/unistd/close.h"
+#include "src/unistd/fchown.h"
+#include "src/unistd/getgid.h"
+#include "src/unistd/getuid.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"
+#include <sys/stat.h>
+
+using LlvmLibcFchownTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;
+
+TEST_F(LlvmLibcFchownTest, FchownSuccess) {
+ using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
+ uid_t my_uid = LIBC_NAMESPACE::getuid();
+ gid_t my_gid = LIBC_NAMESPACE::getgid();
+ constexpr const char *FILENAME = "fchown.test";
+ auto TEST_FILE = libc_make_test_file_path(FILENAME);
+
+ // Create a test file.
+ int write_fd = LIBC_NAMESPACE::open(TEST_FILE, O_WRONLY | O_CREAT, S_IRWXU);
+ ASSERT_ERRNO_SUCCESS();
+ ASSERT_GT(write_fd, 0);
+
+ // Change the ownership of the file.
+ ASSERT_THAT(LIBC_NAMESPACE::fchown(write_fd, my_uid, my_gid), Succeeds(0));
+
+ // Close the file descriptor.
+ ASSERT_THAT(LIBC_NAMESPACE::close(write_fd), Succeeds(0));
+
+ // Clean up the test file.
+ ASSERT_THAT(LIBC_NAMESPACE::unlink(TEST_FILE), Succeeds(0));
+}
+
+TEST_F(LlvmLibcFchownTest, FchownInvalidFileDescriptor) {
+ using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails;
+ ASSERT_THAT(LIBC_NAMESPACE::fchown(-1, 1000, 1000), Fails(EBADF));
+}