1 //===--- Implementation of the Linux specialization of File ---------------===//
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
7 //===----------------------------------------------------------------------===//
11 #include "src/__support/File/file.h"
13 #include "src/__support/CPP/new.h"
14 #include "src/__support/File/linux/lseekImpl.h"
15 #include "src/__support/OSUtil/syscall.h" // For internal syscall function.
16 #include "src/errno/libc_errno.h" // For error macros
18 #include <fcntl.h> // For mode_t and other flags to the open syscall
20 #include <sys/syscall.h> // For syscall numbers
22 namespace LIBC_NAMESPACE
{
24 FileIOResult
linux_file_write(File
*f
, const void *data
, size_t size
) {
25 auto *lf
= reinterpret_cast<LinuxFile
*>(f
);
27 LIBC_NAMESPACE::syscall_impl
<int>(SYS_write
, lf
->get_fd(), data
, size
);
34 FileIOResult
linux_file_read(File
*f
, void *buf
, size_t size
) {
35 auto *lf
= reinterpret_cast<LinuxFile
*>(f
);
37 LIBC_NAMESPACE::syscall_impl
<int>(SYS_read
, lf
->get_fd(), buf
, size
);
44 ErrorOr
<long> linux_file_seek(File
*f
, long offset
, int whence
) {
45 auto *lf
= reinterpret_cast<LinuxFile
*>(f
);
46 auto result
= internal::lseekimpl(lf
->get_fd(), offset
, whence
);
47 if (!result
.has_value())
48 return result
.error();
49 return result
.value();
52 int linux_file_close(File
*f
) {
53 auto *lf
= reinterpret_cast<LinuxFile
*>(f
);
54 int ret
= LIBC_NAMESPACE::syscall_impl
<int>(SYS_close
, lf
->get_fd());
62 ErrorOr
<File
*> openfile(const char *path
, const char *mode
) {
63 using ModeFlags
= File::ModeFlags
;
64 auto modeflags
= File::mode_flags(mode
);
66 // return {nullptr, EINVAL};
70 if (modeflags
& ModeFlags(File::OpenMode::APPEND
)) {
71 open_flags
= O_CREAT
| O_APPEND
;
72 if (modeflags
& ModeFlags(File::OpenMode::PLUS
))
75 open_flags
|= O_WRONLY
;
76 } else if (modeflags
& ModeFlags(File::OpenMode::WRITE
)) {
77 open_flags
= O_CREAT
| O_TRUNC
;
78 if (modeflags
& ModeFlags(File::OpenMode::PLUS
))
81 open_flags
|= O_WRONLY
;
83 if (modeflags
& ModeFlags(File::OpenMode::PLUS
))
86 open_flags
|= O_RDONLY
;
89 // File created will have 0666 permissions.
90 constexpr long OPEN_MODE
=
91 S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
| S_IROTH
| S_IWOTH
;
95 LIBC_NAMESPACE::syscall_impl
<int>(SYS_open
, path
, open_flags
, OPEN_MODE
);
96 #elif defined(SYS_openat)
97 int fd
= LIBC_NAMESPACE::syscall_impl
<int>(SYS_openat
, AT_FDCWD
, path
,
98 open_flags
, OPEN_MODE
);
100 #error "open and openat syscalls not available."
109 buffer
= new (ac
) uint8_t[File::DEFAULT_BUFFER_SIZE
];
111 return Error(ENOMEM
);
114 auto *file
= new (ac
)
115 LinuxFile(fd
, buffer
, File::DEFAULT_BUFFER_SIZE
, _IOFBF
, true, modeflags
);
117 return Error(ENOMEM
);
121 int get_fileno(File
*f
) {
122 auto *lf
= reinterpret_cast<LinuxFile
*>(f
);
126 } // namespace LIBC_NAMESPACE