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