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