xref: /llvm-project/libc/src/stdio/fopencookie.cpp (revision 2e4ef9b6efcaacd5556e8c0ddf659550d3a089a0)
1 //===-- Implementation of fopencookie -------------------------------------===//
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/fopencookie.h"
10 #include "src/__support/File/file.h"
11 
12 #include <errno.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 
16 namespace __llvm_libc {
17 
18 namespace {
19 
20 class CookieFile : public __llvm_libc::File {
21 public:
22   void *cookie;
23   cookie_io_functions_t ops;
24 };
25 
26 size_t write_func(File *f, const void *data, size_t size) {
27   auto cookie_file = reinterpret_cast<CookieFile *>(f);
28   if (cookie_file->ops.write == nullptr)
29     return 0;
30   return cookie_file->ops.write(cookie_file->cookie,
31                                 reinterpret_cast<const char *>(data), size);
32 }
33 
34 size_t read_func(File *f, void *data, size_t size) {
35   auto cookie_file = reinterpret_cast<CookieFile *>(f);
36   if (cookie_file->ops.read == nullptr)
37     return 0;
38   return cookie_file->ops.read(cookie_file->cookie,
39                                reinterpret_cast<char *>(data), size);
40 }
41 
42 int seek_func(File *f, long offset, int whence) {
43   auto cookie_file = reinterpret_cast<CookieFile *>(f);
44   if (cookie_file->ops.seek == nullptr) {
45     errno = EINVAL;
46     return -1;
47   }
48   off64_t offset64 = offset;
49   return cookie_file->ops.seek(cookie_file->cookie, &offset64, whence);
50 }
51 
52 int close_func(File *f) {
53   auto cookie_file = reinterpret_cast<CookieFile *>(f);
54   if (cookie_file->ops.close == nullptr)
55     return 0;
56   return cookie_file->ops.close(cookie_file->cookie);
57 }
58 
59 int flush_func(File *) { return 0; }
60 
61 } // anonymous namespace
62 
63 LLVM_LIBC_FUNCTION(::FILE *, fopencookie,
64                    (void *cookie, const char *mode,
65                     cookie_io_functions_t ops)) {
66   auto modeflags = File::mode_flags(mode);
67   void *buffer = malloc(File::DEFAULT_BUFFER_SIZE);
68   auto *file = reinterpret_cast<CookieFile *>(malloc(sizeof(CookieFile)));
69   if (file == nullptr)
70     return nullptr;
71 
72   File::init(file, &write_func, &read_func, &seek_func, &close_func,
73              &flush_func, buffer, File::DEFAULT_BUFFER_SIZE,
74              0,    // Default buffering style
75              true, // Owned buffer
76              modeflags);
77   file->cookie = cookie;
78   file->ops = ops;
79 
80   return reinterpret_cast<::FILE *>(file);
81 }
82 
83 } // namespace __llvm_libc
84