forked from OSchip/llvm-project
[libc] Add POSIX functions dup, dup2, and GNU extension function dup3.
Reviewed By: lntue Differential Revision: https://reviews.llvm.org/D133748
This commit is contained in:
parent
6c089b2af5
commit
8989aa003f
|
@ -113,6 +113,9 @@ set(TARGET_LIBC_ENTRYPOINTS
|
|||
# unistd.h entrypoints
|
||||
libc.src.unistd.chdir
|
||||
libc.src.unistd.close
|
||||
libc.src.unistd.dup
|
||||
libc.src.unistd.dup2
|
||||
libc.src.unistd.dup3
|
||||
libc.src.unistd.fchdir
|
||||
libc.src.unistd.fsync
|
||||
libc.src.unistd.ftruncate
|
||||
|
|
|
@ -113,6 +113,9 @@ set(TARGET_LIBC_ENTRYPOINTS
|
|||
# unistd.h entrypoints
|
||||
libc.src.unistd.chdir
|
||||
libc.src.unistd.close
|
||||
libc.src.unistd.dup
|
||||
libc.src.unistd.dup2
|
||||
libc.src.unistd.dup3
|
||||
libc.src.unistd.fchdir
|
||||
libc.src.unistd.fsync
|
||||
libc.src.unistd.ftruncate
|
||||
|
|
|
@ -70,4 +70,11 @@
|
|||
// has to perform the equivalent of "rmdir" on the path argument.
|
||||
#define AT_REMOVEDIR 0x200
|
||||
|
||||
// Values of SYS_fcntl commands.
|
||||
#define F_DUPFD 0
|
||||
#define F_GETFD 1
|
||||
#define F_SETFD 2
|
||||
#define F_GETFL 3
|
||||
#define F_SETFL 4
|
||||
|
||||
#endif // __LLVM_LIBC_MACROS_LINUX_FCNTL_MACROS_H
|
||||
|
|
|
@ -144,6 +144,20 @@ def GnuExtensions : StandardSpec<"GNUExtensions"> {
|
|||
]
|
||||
>;
|
||||
|
||||
HeaderSpec UniStd = HeaderSpec<
|
||||
"unistd.h",
|
||||
[], // Macros
|
||||
[], // Types
|
||||
[], // Enumerations
|
||||
[
|
||||
FunctionSpec<
|
||||
"dup2",
|
||||
RetValSpec<IntType>,
|
||||
[ArgSpec<IntType>, ArgSpec<IntType>, ArgSpec<IntType>]
|
||||
>,
|
||||
]
|
||||
>;
|
||||
|
||||
let Headers = [
|
||||
CType,
|
||||
FEnv,
|
||||
|
@ -152,5 +166,6 @@ def GnuExtensions : StandardSpec<"GNUExtensions"> {
|
|||
SendFile,
|
||||
StdIO,
|
||||
String,
|
||||
UniStd,
|
||||
];
|
||||
}
|
||||
|
|
|
@ -266,6 +266,21 @@ def POSIX : StandardSpec<"POSIX"> {
|
|||
RetValSpec<IntType>,
|
||||
[ArgSpec<ConstCharPtr>]
|
||||
>,
|
||||
FunctionSpec<
|
||||
"dup",
|
||||
RetValSpec<IntType>,
|
||||
[ArgSpec<IntType>]
|
||||
>,
|
||||
FunctionSpec<
|
||||
"dup2",
|
||||
RetValSpec<IntType>,
|
||||
[ArgSpec<IntType>, ArgSpec<IntType>]
|
||||
>,
|
||||
FunctionSpec<
|
||||
"dup3",
|
||||
RetValSpec<IntType>,
|
||||
[ArgSpec<IntType>, ArgSpec<IntType>, ArgSpec<IntType>]
|
||||
>,
|
||||
FunctionSpec<
|
||||
"fchdir",
|
||||
RetValSpec<IntType>,
|
||||
|
|
|
@ -16,6 +16,27 @@ add_entrypoint_object(
|
|||
.${LIBC_TARGET_OS}.close
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
dup
|
||||
ALIAS
|
||||
DEPENDS
|
||||
.${LIBC_TARGET_OS}.dup
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
dup2
|
||||
ALIAS
|
||||
DEPENDS
|
||||
.${LIBC_TARGET_OS}.dup2
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
dup3
|
||||
ALIAS
|
||||
DEPENDS
|
||||
.${LIBC_TARGET_OS}.dup3
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
fchdir
|
||||
ALIAS
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
//===-- Implementation header for dup ---------------------------*- 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_DUP_H
|
||||
#define LLVM_LIBC_SRC_UNISTD_DUP_H
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
int dup(int fd);
|
||||
|
||||
} // namespace __llvm_libc
|
||||
|
||||
#endif // LLVM_LIBC_SRC_UNISTD_DUP_H
|
|
@ -0,0 +1,20 @@
|
|||
//===-- Implementation header for dup2 --------------------------*- 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_DUP2_H
|
||||
#define LLVM_LIBC_SRC_UNISTD_DUP2_H
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
int dup2(int oldfd, int newfd);
|
||||
|
||||
} // namespace __llvm_libc
|
||||
|
||||
#endif // LLVM_LIBC_SRC_UNISTD_DUP2_H
|
|
@ -0,0 +1,20 @@
|
|||
//===-- Implementation header for dup3 --------------------------*- 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_DUP3_H
|
||||
#define LLVM_LIBC_SRC_UNISTD_DUP3_H
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
int dup3(int oldfd, int newfd, int flags);
|
||||
|
||||
} // namespace __llvm_libc
|
||||
|
||||
#endif // LLVM_LIBC_SRC_UNISTD_DUP3_H
|
|
@ -24,6 +24,46 @@ add_entrypoint_object(
|
|||
libc.src.errno.errno
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
dup
|
||||
SRCS
|
||||
dup.cpp
|
||||
HDRS
|
||||
../dup.h
|
||||
DEPENDS
|
||||
libc.include.unistd
|
||||
libc.include.sys_syscall
|
||||
libc.src.__support.OSUtil.osutil
|
||||
libc.src.errno.errno
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
dup2
|
||||
SRCS
|
||||
dup2.cpp
|
||||
HDRS
|
||||
../dup2.h
|
||||
DEPENDS
|
||||
libc.include.fcntl
|
||||
libc.include.unistd
|
||||
libc.include.sys_syscall
|
||||
libc.src.__support.OSUtil.osutil
|
||||
libc.src.errno.errno
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
dup3
|
||||
SRCS
|
||||
dup3.cpp
|
||||
HDRS
|
||||
../dup3.h
|
||||
DEPENDS
|
||||
libc.include.unistd
|
||||
libc.include.sys_syscall
|
||||
libc.src.__support.OSUtil.osutil
|
||||
libc.src.errno.errno
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
fchdir
|
||||
SRCS
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
//===-- Linux implementation of dup ---------------------------------------===//
|
||||
//
|
||||
// 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/dup.h"
|
||||
|
||||
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
|
||||
#include "src/__support/common.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/syscall.h> // For syscall numbers.
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
LLVM_LIBC_FUNCTION(int, dup, (int fd)) {
|
||||
long ret = __llvm_libc::syscall(SYS_dup, fd);
|
||||
if (ret < 0) {
|
||||
errno = -ret;
|
||||
return -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace __llvm_libc
|
|
@ -0,0 +1,47 @@
|
|||
//===-- Linux implementation of dup2 --------------------------------------===//
|
||||
//
|
||||
// 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/dup2.h"
|
||||
|
||||
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
|
||||
#include "src/__support/common.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/syscall.h> // For syscall numbers.
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
LLVM_LIBC_FUNCTION(int, dup2, (int oldfd, int newfd)) {
|
||||
#ifdef SYS_dup2
|
||||
// If dup2 syscall is available, we make use of directly.
|
||||
long ret = __llvm_libc::syscall(SYS_dup2, oldfd, newfd);
|
||||
#elif defined(SYS_dup3)
|
||||
// If dup2 syscall is not available, we try using the dup3 syscall. However,
|
||||
// dup3 fails if oldfd is the same as newfd. So, we handle that case
|
||||
// separately before making the dup3 syscall.
|
||||
if (oldfd == newfd) {
|
||||
// Check if oldfd is actually a valid file descriptor.
|
||||
long ret = __llvm_libc::syscall(SYS_fcntl, oldfd, F_GETFD);
|
||||
if (ret >= 0)
|
||||
return oldfd;
|
||||
errno = -ret;
|
||||
return -1;
|
||||
}
|
||||
long ret = __llvm_libc::syscall(SYS_dup3, oldfd, newfd, 0);
|
||||
#else
|
||||
#error "SYS_dup2 and SYS_dup3 not available for the target."
|
||||
#endif
|
||||
if (ret < 0) {
|
||||
errno = -ret;
|
||||
return -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace __llvm_libc
|
|
@ -0,0 +1,28 @@
|
|||
//===-- Linux implementation of dup3 --------------------------------------===//
|
||||
//
|
||||
// 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/dup3.h"
|
||||
|
||||
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
|
||||
#include "src/__support/common.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/syscall.h> // For syscall numbers.
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
LLVM_LIBC_FUNCTION(int, dup3, (int oldfd, int newfd, int flags)) {
|
||||
// If dup2 syscall is available, we make use of directly.
|
||||
long ret = __llvm_libc::syscall(SYS_dup3, oldfd, newfd, flags);
|
||||
if (ret >= 0)
|
||||
return ret;
|
||||
errno = -ret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
} // namespace __llvm_libc
|
|
@ -17,6 +17,60 @@ add_libc_unittest(
|
|||
libc.test.errno_setter_matcher
|
||||
)
|
||||
|
||||
add_libc_unittest(
|
||||
dup_test
|
||||
SUITE
|
||||
libc_unistd_unittests
|
||||
SRCS
|
||||
dup_test.cpp
|
||||
DEPENDS
|
||||
libc.include.errno
|
||||
libc.include.unistd
|
||||
libc.src.fcntl.open
|
||||
libc.src.unistd.close
|
||||
libc.src.unistd.dup
|
||||
libc.src.unistd.read
|
||||
libc.src.unistd.unlink
|
||||
libc.src.unistd.write
|
||||
libc.test.errno_setter_matcher
|
||||
)
|
||||
|
||||
add_libc_unittest(
|
||||
dup2_test
|
||||
SUITE
|
||||
libc_unistd_unittests
|
||||
SRCS
|
||||
dup2_test.cpp
|
||||
DEPENDS
|
||||
libc.include.errno
|
||||
libc.include.unistd
|
||||
libc.src.fcntl.open
|
||||
libc.src.unistd.close
|
||||
libc.src.unistd.dup2
|
||||
libc.src.unistd.read
|
||||
libc.src.unistd.unlink
|
||||
libc.src.unistd.write
|
||||
libc.test.errno_setter_matcher
|
||||
)
|
||||
|
||||
add_libc_unittest(
|
||||
dup3_test
|
||||
SUITE
|
||||
libc_unistd_unittests
|
||||
SRCS
|
||||
dup3_test.cpp
|
||||
DEPENDS
|
||||
libc.include.errno
|
||||
libc.include.unistd
|
||||
libc.src.fcntl.open
|
||||
libc.src.unistd.close
|
||||
libc.src.unistd.dup3
|
||||
libc.src.unistd.read
|
||||
libc.src.unistd.unlink
|
||||
libc.src.unistd.write
|
||||
libc.test.errno_setter_matcher
|
||||
)
|
||||
|
||||
add_libc_unittest(
|
||||
fchdir_test
|
||||
SUITE
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
//===-- Unittests for dup -------------------------------------------------===//
|
||||
//
|
||||
// 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/dup2.h"
|
||||
#include "src/unistd/read.h"
|
||||
#include "src/unistd/unlink.h"
|
||||
#include "src/unistd/write.h"
|
||||
#include "test/ErrnoSetterMatcher.h"
|
||||
#include "utils/UnitTest/Test.h"
|
||||
#include "utils/testutils/FDReader.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
TEST(LlvmLibcdupTest, ReadAndWriteViaDup) {
|
||||
constexpr int DUPFD = 0xD0;
|
||||
errno = 0;
|
||||
using __llvm_libc::testing::ErrnoSetterMatcher::Succeeds;
|
||||
constexpr const char *TEST_FILE = "testdata/dup.test";
|
||||
int fd = __llvm_libc::open(TEST_FILE, O_WRONLY | O_CREAT, S_IRWXU);
|
||||
ASSERT_EQ(errno, 0);
|
||||
ASSERT_GT(fd, 0);
|
||||
int dupfd = __llvm_libc::dup2(fd, DUPFD);
|
||||
ASSERT_EQ(errno, 0);
|
||||
ASSERT_EQ(dupfd, DUPFD);
|
||||
|
||||
// Write something via the dup
|
||||
constexpr char WRITE_DATA[] = "Hello, dup!";
|
||||
constexpr size_t WRITE_SIZE = sizeof(WRITE_DATA);
|
||||
ASSERT_EQ(ssize_t(WRITE_SIZE),
|
||||
__llvm_libc::write(dupfd, WRITE_DATA, WRITE_SIZE));
|
||||
ASSERT_THAT(__llvm_libc::close(dupfd), Succeeds(0));
|
||||
|
||||
// Reopen the file for reading and create a dup.
|
||||
fd = __llvm_libc::open(TEST_FILE, O_RDONLY);
|
||||
ASSERT_EQ(errno, 0);
|
||||
ASSERT_GT(fd, 0);
|
||||
dupfd = __llvm_libc::dup2(fd, DUPFD);
|
||||
ASSERT_EQ(errno, 0);
|
||||
ASSERT_EQ(dupfd, DUPFD);
|
||||
|
||||
// Read the file content via the dup.
|
||||
char buf[WRITE_SIZE];
|
||||
ASSERT_THAT(__llvm_libc::read(dupfd, buf, WRITE_SIZE), Succeeds(WRITE_SIZE));
|
||||
ASSERT_STREQ(buf, WRITE_DATA);
|
||||
|
||||
// Verify that duping to the same fd value succeeds.
|
||||
ASSERT_THAT(__llvm_libc::dup2(dupfd, dupfd), Succeeds(dupfd));
|
||||
|
||||
ASSERT_THAT(__llvm_libc::close(dupfd), Succeeds(0));
|
||||
ASSERT_THAT(__llvm_libc::unlink(TEST_FILE), Succeeds(0));
|
||||
}
|
||||
|
||||
TEST(LlvmLibcdupTest, DupBadFD) {
|
||||
using __llvm_libc::testing::ErrnoSetterMatcher::Fails;
|
||||
ASSERT_THAT(__llvm_libc::dup2(-1, 123), Fails(EBADF));
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
//===-- Unittests for dup3 ------------------------------------------------===//
|
||||
//
|
||||
// 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/dup3.h"
|
||||
#include "src/unistd/read.h"
|
||||
#include "src/unistd/unlink.h"
|
||||
#include "src/unistd/write.h"
|
||||
#include "test/ErrnoSetterMatcher.h"
|
||||
#include "utils/UnitTest/Test.h"
|
||||
#include "utils/testutils/FDReader.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
// The tests here are exactly the same as those of dup2. We only test the
|
||||
// plumbing of the dup3 syscall and not the dup3 functionality itself as it is
|
||||
// a simple syscall wrapper. Testing dup3 functionality is beyond the scope of
|
||||
// this test.
|
||||
|
||||
TEST(LlvmLibcdupTest, ReadAndWriteViaDup) {
|
||||
constexpr int DUPFD = 0xD0;
|
||||
errno = 0;
|
||||
using __llvm_libc::testing::ErrnoSetterMatcher::Fails;
|
||||
using __llvm_libc::testing::ErrnoSetterMatcher::Succeeds;
|
||||
constexpr const char *TEST_FILE = "testdata/dup.test";
|
||||
int fd = __llvm_libc::open(TEST_FILE, O_WRONLY | O_CREAT, S_IRWXU);
|
||||
ASSERT_EQ(errno, 0);
|
||||
ASSERT_GT(fd, 0);
|
||||
int dupfd = __llvm_libc::dup3(fd, DUPFD, 0);
|
||||
ASSERT_EQ(errno, 0);
|
||||
ASSERT_EQ(dupfd, DUPFD);
|
||||
|
||||
// Write something via the dup
|
||||
constexpr char WRITE_DATA[] = "Hello, dup!";
|
||||
constexpr size_t WRITE_SIZE = sizeof(WRITE_DATA);
|
||||
ASSERT_EQ(ssize_t(WRITE_SIZE),
|
||||
__llvm_libc::write(dupfd, WRITE_DATA, WRITE_SIZE));
|
||||
ASSERT_THAT(__llvm_libc::close(dupfd), Succeeds(0));
|
||||
|
||||
// Reopen the file for reading and create a dup.
|
||||
fd = __llvm_libc::open(TEST_FILE, O_RDONLY);
|
||||
ASSERT_EQ(errno, 0);
|
||||
ASSERT_GT(fd, 0);
|
||||
dupfd = __llvm_libc::dup3(fd, DUPFD, 0);
|
||||
ASSERT_EQ(errno, 0);
|
||||
ASSERT_EQ(dupfd, DUPFD);
|
||||
|
||||
// Read the file content via the dup.
|
||||
char buf[WRITE_SIZE];
|
||||
ASSERT_THAT(__llvm_libc::read(dupfd, buf, WRITE_SIZE), Succeeds(WRITE_SIZE));
|
||||
ASSERT_STREQ(buf, WRITE_DATA);
|
||||
|
||||
// Verify that, unlike dup2, duping to the same fd value with dup3 fails.
|
||||
ASSERT_THAT(__llvm_libc::dup3(dupfd, dupfd, 0), Fails(EINVAL));
|
||||
|
||||
ASSERT_THAT(__llvm_libc::close(dupfd), Succeeds(0));
|
||||
ASSERT_THAT(__llvm_libc::unlink(TEST_FILE), Succeeds(0));
|
||||
}
|
||||
|
||||
TEST(LlvmLibcdupTest, DupBadFD) {
|
||||
using __llvm_libc::testing::ErrnoSetterMatcher::Fails;
|
||||
ASSERT_THAT(__llvm_libc::dup3(-1, 123, 0), Fails(EBADF));
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
//===-- Unittests for dup -------------------------------------------------===//
|
||||
//
|
||||
// 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/dup.h"
|
||||
#include "src/unistd/read.h"
|
||||
#include "src/unistd/unlink.h"
|
||||
#include "src/unistd/write.h"
|
||||
#include "test/ErrnoSetterMatcher.h"
|
||||
#include "utils/UnitTest/Test.h"
|
||||
#include "utils/testutils/FDReader.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
TEST(LlvmLibcdupTest, ReadAndWriteViaDup) {
|
||||
errno = 0;
|
||||
using __llvm_libc::testing::ErrnoSetterMatcher::Succeeds;
|
||||
constexpr const char *TEST_FILE = "testdata/dup.test";
|
||||
int fd = __llvm_libc::open(TEST_FILE, O_WRONLY | O_CREAT, S_IRWXU);
|
||||
ASSERT_EQ(errno, 0);
|
||||
ASSERT_GT(fd, 0);
|
||||
int dupfd = __llvm_libc::dup(fd);
|
||||
ASSERT_EQ(errno, 0);
|
||||
ASSERT_GT(dupfd, 0);
|
||||
|
||||
// Write something via the dup
|
||||
constexpr char WRITE_DATA[] = "Hello, dup!";
|
||||
constexpr size_t WRITE_SIZE = sizeof(WRITE_DATA);
|
||||
ASSERT_EQ(ssize_t(WRITE_SIZE),
|
||||
__llvm_libc::write(dupfd, WRITE_DATA, WRITE_SIZE));
|
||||
ASSERT_THAT(__llvm_libc::close(dupfd), Succeeds(0));
|
||||
|
||||
// Reopen the file for reading and create a dup.
|
||||
fd = __llvm_libc::open(TEST_FILE, O_RDONLY);
|
||||
ASSERT_EQ(errno, 0);
|
||||
ASSERT_GT(fd, 0);
|
||||
dupfd = __llvm_libc::dup(fd);
|
||||
ASSERT_EQ(errno, 0);
|
||||
ASSERT_GT(dupfd, 0);
|
||||
|
||||
// Read the file content via the dup.
|
||||
char buf[WRITE_SIZE];
|
||||
ASSERT_THAT(__llvm_libc::read(dupfd, buf, WRITE_SIZE), Succeeds(WRITE_SIZE));
|
||||
ASSERT_STREQ(buf, WRITE_DATA);
|
||||
|
||||
ASSERT_THAT(__llvm_libc::close(dupfd), Succeeds(0));
|
||||
ASSERT_THAT(__llvm_libc::unlink(TEST_FILE), Succeeds(0));
|
||||
}
|
||||
|
||||
TEST(LlvmLibcdupTest, DupBadFD) {
|
||||
using __llvm_libc::testing::ErrnoSetterMatcher::Fails;
|
||||
ASSERT_THAT(__llvm_libc::dup(-1), Fails(EBADF));
|
||||
}
|
Loading…
Reference in New Issue