Skip to content

Commit 4039fdb

Browse files
cowtoolzjhuber6michaelrj-google
authored
[libc] add ioctl (#141393)
Closes #85275 Closes #90317 Updates #97191 --------- Co-authored-by: Joseph Huber <huberjn@outlook.com> Co-authored-by: Michael Jones <michaelrj@google.com>
1 parent c6da2c8 commit 4039fdb

File tree

16 files changed

+219
-0
lines changed

16 files changed

+219
-0
lines changed

libc/config/linux/aarch64/entrypoints.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,9 @@ set(TARGET_LIBC_ENTRYPOINTS
245245
# https://github.com/llvm/llvm-project/issues/80060
246246
# libc.src.sys.epoll.epoll_pwait2
247247

248+
# sys/ioctl.h entrypoints
249+
libc.src.sys.ioctl.ioctl
250+
248251
# sys/mman.h entrypoints
249252
libc.src.sys.mman.madvise
250253
libc.src.sys.mman.mincore

libc/config/linux/arm/entrypoints.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,9 @@ set(TARGET_LIBC_ENTRYPOINTS
172172
libc.src.stdlib.free
173173
libc.src.stdlib.malloc
174174

175+
# sys/ioctl.h entrypoints
176+
libc.src.sys.ioctl.ioctl
177+
175178
# sys/mman.h entrypoints
176179
libc.src.sys.mman.mmap
177180
libc.src.sys.mman.munmap

libc/config/linux/riscv/entrypoints.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,9 @@ set(TARGET_LIBC_ENTRYPOINTS
246246
# https://github.com/llvm/llvm-project/issues/80060
247247
# libc.src.sys.epoll.epoll_pwait2
248248

249+
# sys/ioctl.h entrypoints
250+
libc.src.sys.ioctl.ioctl
251+
249252
# sys/mman.h entrypoints
250253
libc.src.sys.mman.madvise
251254
libc.src.sys.mman.mincore

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,9 @@ set(TARGET_LIBC_ENTRYPOINTS
246246
# https://github.com/llvm/llvm-project/issues/80060
247247
# libc.src.sys.epoll.epoll_pwait2
248248

249+
# sys/ioctl.h entrypoints
250+
libc.src.sys.ioctl.ioctl
251+
249252
# sys/mman.h entrypoints
250253
libc.src.sys.mman.madvise
251254
libc.src.sys.mman.mincore

libc/hdr/CMakeLists.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,15 @@ add_proxy_header_library(
126126
libc.include.llvm-libc-macros.sys_epoll_macros
127127
)
128128

129+
add_proxy_header_library(
130+
sys_ioctl_macros
131+
HDRS
132+
sys_ioctl_macros.h
133+
FULL_BUILD_DEPENDS
134+
libc.include.sys_ioctl
135+
libc.include.llvm-libc-macros.sys_ioctl_macros
136+
)
137+
129138
add_proxy_header_library(
130139
sys_stat_macros
131140
HDRS

libc/hdr/sys_ioctl_macros.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//===-- Definition of macros from sys/ioctl.h -----------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_HDR_SYS_IOCTL_MACROS_H
10+
#define LLVM_LIBC_HDR_SYS_IOCTL_MACROS_H
11+
12+
#ifdef LIBC_FULL_BUILD
13+
14+
#include "include/llvm-libc-macros/sys-ioctl-macros.h"
15+
16+
#else // Overlay mode
17+
18+
#include <sys/ioctl.h>
19+
20+
#endif // LLVM_LIBC_FULL_BUILD
21+
22+
#endif // LLVM_LIBC_HDR_SYS_IOCTL_MACROS_H

libc/include/llvm-libc-macros/linux/sys-ioctl-macros.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,6 @@
1515
// around the definitions of macros like _IO, _IOR, _IOW, and _IOWR that I don't
1616
// think is worth digging into right now.
1717
#define TIOCGETD 0x5424
18+
#define FIONREAD 0x541B
1819

1920
#endif // LLVM_LIBC_MACROS_LINUX_SYS_IOCTL_MACROS_H

libc/src/sys/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ add_subdirectory(utsname)
1313
add_subdirectory(wait)
1414
add_subdirectory(prctl)
1515
add_subdirectory(uio)
16+
add_subdirectory(ioctl)

libc/src/sys/ioctl/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
2+
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
3+
endif()
4+
5+
add_entrypoint_object(
6+
ioctl
7+
ALIAS
8+
DEPENDS
9+
.${LIBC_TARGET_OS}.ioctl
10+
)

libc/src/sys/ioctl/ioctl.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===-- Implementation header for ioctl ---------------------------*-C++-*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_SRC_SYS_IOCTL_IOCTL_H
10+
#define LLVM_LIBC_SRC_SYS_IOCTL_IOCTL_H
11+
12+
#include "src/__support/macros/config.h"
13+
14+
namespace LIBC_NAMESPACE_DECL {
15+
16+
int ioctl(int fd, unsigned long request, ...);
17+
18+
} // namespace LIBC_NAMESPACE_DECL
19+
20+
#endif // LLVM_LIBC_SRC_SYS_IOCTL_IOCTL_H
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
add_entrypoint_object(
2+
ioctl
3+
SRCS
4+
ioctl.cpp
5+
HDRS
6+
../ioctl.h
7+
DEPENDS
8+
libc.include.sys_ioctl
9+
libc.include.sys_syscall
10+
libc.src.__support.OSUtil.osutil
11+
libc.src.errno.errno
12+
)

libc/src/sys/ioctl/linux/ioctl.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//===---------- Linux implementation of the ioctl function ----------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "src/sys/ioctl/ioctl.h"
10+
11+
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
12+
#include "src/__support/common.h"
13+
#include "src/errno/libc_errno.h"
14+
#include <stdarg.h>
15+
#include <sys/syscall.h> // For syscall numbers.
16+
17+
namespace LIBC_NAMESPACE_DECL {
18+
19+
LLVM_LIBC_FUNCTION(int, ioctl, (int fd, unsigned long request, ...)) {
20+
va_list vargs;
21+
va_start(vargs, request);
22+
void *data_pointer = va_arg(vargs, void *);
23+
int ret =
24+
LIBC_NAMESPACE::syscall_impl<int>(SYS_ioctl, fd, request, data_pointer);
25+
va_end(vargs);
26+
27+
// Some ioctls can be expected to return positive values
28+
if (ret >= 0)
29+
return ret;
30+
31+
// If there is an error, errno is set and -1 is returned.
32+
libc_errno = -ret;
33+
return -1;
34+
}
35+
36+
} // namespace LIBC_NAMESPACE_DECL

libc/test/src/sys/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ add_subdirectory(auxv)
1313
add_subdirectory(epoll)
1414
add_subdirectory(uio)
1515
add_subdirectory(time)
16+
add_subdirectory(ioctl)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
2+
add_subdirectory(${LIBC_TARGET_OS})
3+
endif()
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
add_custom_target(libc_sys_ioctl_unittests)
2+
3+
add_libc_unittest(
4+
ioctl_test
5+
SUITE
6+
libc_sys_ioctl_unittests
7+
SRCS
8+
ioctl_test.cpp
9+
DEPENDS
10+
libc.hdr.ioctl_macros
11+
libc.src.sys.ioctl.ioctl
12+
libc.src.errno.errno
13+
libc.src.fcntl.open
14+
libc.src.unistd.close
15+
libc.src.unistd.read
16+
libc.src.unistd.write
17+
)
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
//===-- Unittests for ioctl -----------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "src/errno/libc_errno.h"
10+
#include "src/fcntl/open.h"
11+
#include "src/sys/ioctl/ioctl.h"
12+
#include "src/unistd/close.h"
13+
#include "src/unistd/read.h"
14+
#include "src/unistd/write.h"
15+
16+
#include "test/UnitTest/ErrnoSetterMatcher.h"
17+
#include "test/UnitTest/Test.h"
18+
19+
#include "hdr/sys_stat_macros.h"
20+
21+
#include "hdr/sys_ioctl_macros.h"
22+
23+
using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
24+
25+
TEST(LlvmLibcSysIoctlTest, InvalidCommandAndFIONREAD) {
26+
LIBC_NAMESPACE::libc_errno = 0;
27+
28+
// Setup the test file
29+
constexpr const char *TEST_FILE_NAME = "ioctl.test";
30+
constexpr const char TEST_MSG[] = "ioctl test";
31+
constexpr int TEST_MSG_SIZE = sizeof(TEST_MSG) - 1;
32+
auto TEST_FILE = libc_make_test_file_path(TEST_FILE_NAME);
33+
int new_test_file_fd = LIBC_NAMESPACE::open(
34+
TEST_FILE, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
35+
ASSERT_THAT(
36+
(int)LIBC_NAMESPACE::write(new_test_file_fd, TEST_MSG, TEST_MSG_SIZE),
37+
Succeeds(TEST_MSG_SIZE));
38+
ASSERT_ERRNO_SUCCESS();
39+
ASSERT_THAT(LIBC_NAMESPACE::close(new_test_file_fd), Succeeds(0));
40+
ASSERT_ERRNO_SUCCESS();
41+
42+
// Reopen the file for testing
43+
int fd = LIBC_NAMESPACE::open(TEST_FILE, O_RDONLY);
44+
ASSERT_ERRNO_SUCCESS();
45+
ASSERT_GT(fd, 0);
46+
47+
// FIONREAD reports the number of available bytes to read for the passed fd
48+
// This will report the full size of the file, as we haven't read anything yet
49+
int n = -1;
50+
int ret = LIBC_NAMESPACE::ioctl(fd, FIONREAD, &n);
51+
ASSERT_ERRNO_SUCCESS();
52+
ASSERT_GT(ret, -1);
53+
ASSERT_EQ(n, TEST_MSG_SIZE);
54+
55+
// But if we read some bytes...
56+
constexpr int READ_COUNT = 5;
57+
char read_buffer[READ_COUNT];
58+
ASSERT_THAT((int)LIBC_NAMESPACE::read(fd, read_buffer, READ_COUNT),
59+
Succeeds(READ_COUNT));
60+
61+
// ... n should have decreased by the number of bytes we've read
62+
int n_after_reading = -1;
63+
ret = LIBC_NAMESPACE::ioctl(fd, FIONREAD, &n_after_reading);
64+
ASSERT_ERRNO_SUCCESS();
65+
ASSERT_GT(ret, -1);
66+
ASSERT_EQ(n - READ_COUNT, n_after_reading);
67+
68+
// 0xDEADBEEF is just a random nonexistent command;
69+
// calling this should always fail with ENOTTY
70+
ret = LIBC_NAMESPACE::ioctl(fd, 0xDEADBEEF, NULL);
71+
ASSERT_ERRNO_EQ(ENOTTY);
72+
ASSERT_EQ(ret, -1);
73+
74+
ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));
75+
}

0 commit comments

Comments
 (0)