//===-- Implementation of fopencookie -------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "src/stdio/fopencookie.h" #include "src/__support/File/file.h" #include #include #include namespace __llvm_libc { namespace { class CookieFile : public __llvm_libc::File { public: void *cookie; cookie_io_functions_t ops; }; size_t write_func(File *f, const void *data, size_t size) { auto cookie_file = reinterpret_cast(f); if (cookie_file->ops.write == nullptr) return 0; return cookie_file->ops.write(cookie_file->cookie, reinterpret_cast(data), size); } size_t read_func(File *f, void *data, size_t size) { auto cookie_file = reinterpret_cast(f); if (cookie_file->ops.read == nullptr) return 0; return cookie_file->ops.read(cookie_file->cookie, reinterpret_cast(data), size); } int seek_func(File *f, long offset, int whence) { auto cookie_file = reinterpret_cast(f); if (cookie_file->ops.seek == nullptr) { errno = EINVAL; return -1; } off64_t offset64 = offset; return cookie_file->ops.seek(cookie_file->cookie, &offset64, whence); } int close_func(File *f) { auto cookie_file = reinterpret_cast(f); if (cookie_file->ops.close == nullptr) return 0; return cookie_file->ops.close(cookie_file->cookie); } int flush_func(File *) { return 0; } } // anonymous namespace LLVM_LIBC_FUNCTION(::FILE *, fopencookie, (void *cookie, const char *mode, cookie_io_functions_t ops)) { auto modeflags = File::mode_flags(mode); void *buffer = malloc(File::DEFAULT_BUFFER_SIZE); auto *file = reinterpret_cast(malloc(sizeof(CookieFile))); if (file == nullptr) return nullptr; File::init(file, &write_func, &read_func, &seek_func, &close_func, &flush_func, buffer, File::DEFAULT_BUFFER_SIZE, 0, // Default buffering style true, // Owned buffer modeflags); file->cookie = cookie; file->ops = ops; return reinterpret_cast<::FILE *>(file); } } // namespace __llvm_libc