[clang][modules] Don't prevent translation of FW_Private includes when explicitly...
[llvm-project.git] / libc / src / __support / File / linux / file.cpp
blob2d4cea5b53c5815c8ff9a3f5a1387a27c8b17c2a
1 //===--- Implementation of the Linux specialization of File ---------------===//
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 //===----------------------------------------------------------------------===//
9 #include "file.h"
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
19 #include <stdio.h>
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);
26 int ret =
27 LIBC_NAMESPACE::syscall_impl<int>(SYS_write, lf->get_fd(), data, size);
28 if (ret < 0) {
29 return {0, -ret};
31 return ret;
34 FileIOResult linux_file_read(File *f, void *buf, size_t size) {
35 auto *lf = reinterpret_cast<LinuxFile *>(f);
36 int ret =
37 LIBC_NAMESPACE::syscall_impl<int>(SYS_read, lf->get_fd(), buf, size);
38 if (ret < 0) {
39 return {0, -ret};
41 return ret;
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());
55 if (ret < 0) {
56 return -ret;
58 delete lf;
59 return 0;
62 ErrorOr<File *> openfile(const char *path, const char *mode) {
63 using ModeFlags = File::ModeFlags;
64 auto modeflags = File::mode_flags(mode);
65 if (modeflags == 0) {
66 // return {nullptr, EINVAL};
67 return Error(EINVAL);
69 long open_flags = 0;
70 if (modeflags & ModeFlags(File::OpenMode::APPEND)) {
71 open_flags = O_CREAT | O_APPEND;
72 if (modeflags & ModeFlags(File::OpenMode::PLUS))
73 open_flags |= O_RDWR;
74 else
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))
79 open_flags |= O_RDWR;
80 else
81 open_flags |= O_WRONLY;
82 } else {
83 if (modeflags & ModeFlags(File::OpenMode::PLUS))
84 open_flags |= O_RDWR;
85 else
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;
93 #ifdef SYS_open
94 int fd =
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);
99 #else
100 #error "open and openat syscalls not available."
101 #endif
103 if (fd < 0)
104 return Error(-fd);
106 uint8_t *buffer;
108 AllocChecker ac;
109 buffer = new (ac) uint8_t[File::DEFAULT_BUFFER_SIZE];
110 if (!ac)
111 return Error(ENOMEM);
113 AllocChecker ac;
114 auto *file = new (ac)
115 LinuxFile(fd, buffer, File::DEFAULT_BUFFER_SIZE, _IOFBF, true, modeflags);
116 if (!ac)
117 return Error(ENOMEM);
118 return file;
121 int get_fileno(File *f) {
122 auto *lf = reinterpret_cast<LinuxFile *>(f);
123 return lf->get_fd();
126 } // namespace LIBC_NAMESPACE