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
write_func(File * f,const void * data,size_t size)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
read_func(File * f,void * data,size_t size)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
seek_func(File * f,long offset,int whence)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
close_func(File * f)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
flush_func(File * f)59 int flush_func(File *f) { 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