1*19a6dd33SSiva Chandra Reddy //===-- Implementation of fopencookie -------------------------------------===//
2*19a6dd33SSiva Chandra Reddy //
3*19a6dd33SSiva Chandra Reddy // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*19a6dd33SSiva Chandra Reddy // See https://llvm.org/LICENSE.txt for license information.
5*19a6dd33SSiva Chandra Reddy // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*19a6dd33SSiva Chandra Reddy //
7*19a6dd33SSiva Chandra Reddy //===----------------------------------------------------------------------===//
8*19a6dd33SSiva Chandra Reddy 
9*19a6dd33SSiva Chandra Reddy #include "src/stdio/fopencookie.h"
10*19a6dd33SSiva Chandra Reddy #include "src/__support/File/file.h"
11*19a6dd33SSiva Chandra Reddy 
12*19a6dd33SSiva Chandra Reddy #include <errno.h>
13*19a6dd33SSiva Chandra Reddy #include <stdio.h>
14*19a6dd33SSiva Chandra Reddy #include <stdlib.h>
15*19a6dd33SSiva Chandra Reddy 
16*19a6dd33SSiva Chandra Reddy namespace __llvm_libc {
17*19a6dd33SSiva Chandra Reddy 
18*19a6dd33SSiva Chandra Reddy namespace {
19*19a6dd33SSiva Chandra Reddy 
20*19a6dd33SSiva Chandra Reddy class CookieFile : public __llvm_libc::File {
21*19a6dd33SSiva Chandra Reddy public:
22*19a6dd33SSiva Chandra Reddy   void *cookie;
23*19a6dd33SSiva Chandra Reddy   cookie_io_functions_t ops;
24*19a6dd33SSiva Chandra Reddy };
25*19a6dd33SSiva Chandra Reddy 
write_func(File * f,const void * data,size_t size)26*19a6dd33SSiva Chandra Reddy size_t write_func(File *f, const void *data, size_t size) {
27*19a6dd33SSiva Chandra Reddy   auto cookie_file = reinterpret_cast<CookieFile *>(f);
28*19a6dd33SSiva Chandra Reddy   if (cookie_file->ops.write == nullptr)
29*19a6dd33SSiva Chandra Reddy     return 0;
30*19a6dd33SSiva Chandra Reddy   return cookie_file->ops.write(cookie_file->cookie,
31*19a6dd33SSiva Chandra Reddy                                 reinterpret_cast<const char *>(data), size);
32*19a6dd33SSiva Chandra Reddy }
33*19a6dd33SSiva Chandra Reddy 
read_func(File * f,void * data,size_t size)34*19a6dd33SSiva Chandra Reddy size_t read_func(File *f, void *data, size_t size) {
35*19a6dd33SSiva Chandra Reddy   auto cookie_file = reinterpret_cast<CookieFile *>(f);
36*19a6dd33SSiva Chandra Reddy   if (cookie_file->ops.read == nullptr)
37*19a6dd33SSiva Chandra Reddy     return 0;
38*19a6dd33SSiva Chandra Reddy   return cookie_file->ops.read(cookie_file->cookie,
39*19a6dd33SSiva Chandra Reddy                                reinterpret_cast<char *>(data), size);
40*19a6dd33SSiva Chandra Reddy }
41*19a6dd33SSiva Chandra Reddy 
seek_func(File * f,long offset,int whence)42*19a6dd33SSiva Chandra Reddy int seek_func(File *f, long offset, int whence) {
43*19a6dd33SSiva Chandra Reddy   auto cookie_file = reinterpret_cast<CookieFile *>(f);
44*19a6dd33SSiva Chandra Reddy   if (cookie_file->ops.seek == nullptr) {
45*19a6dd33SSiva Chandra Reddy     errno = EINVAL;
46*19a6dd33SSiva Chandra Reddy     return -1;
47*19a6dd33SSiva Chandra Reddy   }
48*19a6dd33SSiva Chandra Reddy   off64_t offset64 = offset;
49*19a6dd33SSiva Chandra Reddy   return cookie_file->ops.seek(cookie_file->cookie, &offset64, whence);
50*19a6dd33SSiva Chandra Reddy }
51*19a6dd33SSiva Chandra Reddy 
close_func(File * f)52*19a6dd33SSiva Chandra Reddy int close_func(File *f) {
53*19a6dd33SSiva Chandra Reddy   auto cookie_file = reinterpret_cast<CookieFile *>(f);
54*19a6dd33SSiva Chandra Reddy   if (cookie_file->ops.close == nullptr)
55*19a6dd33SSiva Chandra Reddy     return 0;
56*19a6dd33SSiva Chandra Reddy   return cookie_file->ops.close(cookie_file->cookie);
57*19a6dd33SSiva Chandra Reddy }
58*19a6dd33SSiva Chandra Reddy 
flush_func(File * f)59*19a6dd33SSiva Chandra Reddy int flush_func(File *f) { return 0; }
60*19a6dd33SSiva Chandra Reddy 
61*19a6dd33SSiva Chandra Reddy } // anonymous namespace
62*19a6dd33SSiva Chandra Reddy 
63*19a6dd33SSiva Chandra Reddy LLVM_LIBC_FUNCTION(::FILE *, fopencookie,
64*19a6dd33SSiva Chandra Reddy                    (void *cookie, const char *mode,
65*19a6dd33SSiva Chandra Reddy                     cookie_io_functions_t ops)) {
66*19a6dd33SSiva Chandra Reddy   auto modeflags = File::mode_flags(mode);
67*19a6dd33SSiva Chandra Reddy   void *buffer = malloc(File::DEFAULT_BUFFER_SIZE);
68*19a6dd33SSiva Chandra Reddy   auto *file = reinterpret_cast<CookieFile *>(malloc(sizeof(CookieFile)));
69*19a6dd33SSiva Chandra Reddy   if (file == nullptr)
70*19a6dd33SSiva Chandra Reddy     return nullptr;
71*19a6dd33SSiva Chandra Reddy 
72*19a6dd33SSiva Chandra Reddy   File::init(file, &write_func, &read_func, &seek_func, &close_func,
73*19a6dd33SSiva Chandra Reddy              &flush_func, buffer, File::DEFAULT_BUFFER_SIZE,
74*19a6dd33SSiva Chandra Reddy              0,    // Default buffering style
75*19a6dd33SSiva Chandra Reddy              true, // Owned buffer
76*19a6dd33SSiva Chandra Reddy              modeflags);
77*19a6dd33SSiva Chandra Reddy   file->cookie = cookie;
78*19a6dd33SSiva Chandra Reddy   file->ops = ops;
79*19a6dd33SSiva Chandra Reddy 
80*19a6dd33SSiva Chandra Reddy   return reinterpret_cast<::FILE *>(file);
81*19a6dd33SSiva Chandra Reddy }
82*19a6dd33SSiva Chandra Reddy 
83*19a6dd33SSiva Chandra Reddy } // namespace __llvm_libc
84