Skip to content

Commit ac070ea

Browse files
committed
[libc] Add the implementation of the fdopen function
1 parent 718331f commit ac070ea

File tree

9 files changed

+128
-0
lines changed

9 files changed

+128
-0
lines changed

libc/config/linux/aarch64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ set(TARGET_LIBC_ENTRYPOINTS
201201
libc.src.stdio.snprintf
202202
libc.src.stdio.vsprintf
203203
libc.src.stdio.vsnprintf
204+
libc.src.stdio.fdopen
204205
#libc.src.stdio.sscanf
205206
#libc.src.stdio.scanf
206207
#libc.src.stdio.fscanf

libc/config/linux/riscv/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ set(TARGET_LIBC_ENTRYPOINTS
209209
libc.src.stdio.sscanf
210210
libc.src.stdio.scanf
211211
libc.src.stdio.fscanf
212+
libc.src.stdio.fdopen
212213

213214
# sys/mman.h entrypoints
214215
libc.src.sys.mman.madvise

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ set(TARGET_LIBC_ENTRYPOINTS
215215
libc.src.stdio.scanf
216216
libc.src.stdio.fscanf
217217
libc.src.stdio.fileno
218+
libc.src.stdio.fdopen
218219

219220
# sys/epoll.h entrypoints
220221
libc.src.sys.epoll.epoll_create

libc/spec/posix.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1293,6 +1293,11 @@ def POSIX : StandardSpec<"POSIX"> {
12931293
RetValSpec<IntType>,
12941294
[ArgSpec<FILEPtr>]
12951295
>,
1296+
FunctionSpec<
1297+
"fdopen",
1298+
RetValSpec<FILEPtr>,
1299+
[ArgSpec<IntType>, ArgSpec<ConstCharPtr>]
1300+
>,
12961301
]
12971302
>;
12981303

libc/src/stdio/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,13 @@ add_entrypoint_object(
263263
.${LIBC_TARGET_OS}.rename
264264
)
265265

266+
add_entrypoint_object(
267+
fdopen
268+
ALIAS
269+
DEPENDS
270+
.${LIBC_TARGET_OS}.fdopen
271+
)
272+
266273
# These entrypoints have multiple potential implementations.
267274
add_stdio_entrypoint_object(feof)
268275
add_stdio_entrypoint_object(feof_unlocked)

libc/src/stdio/fdopen.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===-- Implementation header of open ---------------------------*- 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_STDIO_FDOPEN_H
10+
#define LLVM_LIBC_SRC_STDIO_FDOPEN_H
11+
12+
#include <stdio.h>
13+
14+
namespace LIBC_NAMESPACE {
15+
16+
FILE *fdopen(int fd, const char *mode);
17+
18+
} // namespace LIBC_NAMESPACE
19+
20+
#endif // LLVM_LIBC_SRC_STDIO_FDOPEN_H

libc/src/stdio/linux/CMakeLists.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,17 @@ add_entrypoint_object(
2424
libc.src.__support.OSUtil.osutil
2525
libc.src.errno.errno
2626
)
27+
28+
add_entrypoint_object(
29+
fdopen
30+
SRCS
31+
fdopen.cpp
32+
HDRS
33+
../fdopen.h
34+
DEPENDS
35+
libc.include.fcntl
36+
libc.include.stdio
37+
libc.src.errno.errno
38+
libc.src.fcntl.fcntl
39+
libc.src.stdio.fseek
40+
)

libc/src/stdio/linux/fdopen.cpp

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
//===-- Implementation of fprintf -------------------------------*- 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+
#include "src/stdio/fdopen.h"
10+
11+
#include "include/llvm-libc-macros/generic-error-number-macros.h"
12+
#include "include/llvm-libc-macros/linux/fcntl-macros.h"
13+
#include "src/__support/File/linux/file.h"
14+
#include "src/errno/libc_errno.h"
15+
#include "src/fcntl/fcntl.h"
16+
#include "src/stdio/fseek.h"
17+
18+
#include <stdio.h>
19+
20+
namespace LIBC_NAMESPACE {
21+
22+
LLVM_LIBC_FUNCTION(::FILE *, fdopen, (int fd, const char *mode)) {
23+
auto modeflags = LIBC_NAMESPACE::File::mode_flags(mode);
24+
if (modeflags == 0) {
25+
libc_errno = EINVAL;
26+
return nullptr;
27+
}
28+
29+
int fd_flags = LIBC_NAMESPACE::fcntl(fd, F_GETFL);
30+
if (fd_flags == -1) {
31+
libc_errno = EBADF;
32+
return nullptr;
33+
}
34+
35+
using OpenMode = File::OpenMode;
36+
if (((fd_flags & O_ACCMODE) == O_RDONLY &&
37+
!(modeflags & static_cast<ModeFlags>(OpenMode::READ))) ||
38+
((fd_flags & O_ACCMODE) == O_WRONLY &&
39+
!(modeflags & static_cast<ModeFlags>(OpenMode::WRITE)))) {
40+
libc_errno = EINVAL;
41+
return nullptr;
42+
}
43+
44+
bool do_seek = false;
45+
if ((modeflags & static_cast<File::ModeFlags>(File::OpenMode::APPEND)) &&
46+
!(fd_flags & O_APPEND)) {
47+
do_seek = true;
48+
if (LIBC_NAMESPACE::fcntl(fd, F_SETFL, fd_flags | O_APPEND) == -1) {
49+
libc_errno = EBADF;
50+
return nullptr;
51+
}
52+
}
53+
54+
uint8_t *buffer;
55+
{
56+
AllocChecker ac;
57+
buffer = new (ac) uint8_t[File::DEFAULT_BUFFER_SIZE];
58+
if (!ac) {
59+
libc_errno = ENOMEM;
60+
return nullptr;
61+
}
62+
}
63+
AllocChecker ac;
64+
auto *linux_file = new (ac)
65+
LinuxFile(fd, buffer, File::DEFAULT_BUFFER_SIZE, _IOFBF, true, modeflags);
66+
if (!ac) {
67+
libc_errno = ENOMEM;
68+
return nullptr;
69+
}
70+
auto *file = reinterpret_cast<::FILE *>(linux_file);
71+
if (do_seek && LIBC_NAMESPACE::fseek(file, 0, SEEK_END) != 0) {
72+
free(linux_file);
73+
return nullptr;
74+
}
75+
76+
return file;
77+
}
78+
79+
} // namespace LIBC_NAMESPACE

libc/test/src/stdio/fdopen_test.cpp

Whitespace-only changes.

0 commit comments

Comments
 (0)