119a6dd33SSiva Chandra Reddy //===-- Implementation of fopencookie -------------------------------------===// 219a6dd33SSiva Chandra Reddy // 319a6dd33SSiva Chandra Reddy // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 419a6dd33SSiva Chandra Reddy // See https://llvm.org/LICENSE.txt for license information. 519a6dd33SSiva Chandra Reddy // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 619a6dd33SSiva Chandra Reddy // 719a6dd33SSiva Chandra Reddy //===----------------------------------------------------------------------===// 819a6dd33SSiva Chandra Reddy 919a6dd33SSiva Chandra Reddy #include "src/stdio/fopencookie.h" 105aed6d67SMichael Jones #include "hdr/stdio_macros.h" 115aed6d67SMichael Jones #include "hdr/types/FILE.h" 125aed6d67SMichael Jones #include "hdr/types/cookie_io_functions_t.h" 135aed6d67SMichael Jones #include "hdr/types/off_t.h" 14d06308dfSSiva Chandra Reddy #include "src/__support/CPP/new.h" 1519a6dd33SSiva Chandra Reddy #include "src/__support/File/file.h" 1619a6dd33SSiva Chandra Reddy 175ff3ff33SPetr Hosek #include "src/__support/macros/config.h" 1804a9c625SMichael Jones #include "src/errno/libc_errno.h" 1919a6dd33SSiva Chandra Reddy 205ff3ff33SPetr Hosek namespace LIBC_NAMESPACE_DECL { 2119a6dd33SSiva Chandra Reddy 2219a6dd33SSiva Chandra Reddy namespace { 2319a6dd33SSiva Chandra Reddy 24b6bc9d72SGuillaume Chatelet class CookieFile : public LIBC_NAMESPACE::File { 2519a6dd33SSiva Chandra Reddy void *cookie; 2619a6dd33SSiva Chandra Reddy cookie_io_functions_t ops; 27d06308dfSSiva Chandra Reddy 28d06308dfSSiva Chandra Reddy static FileIOResult cookie_write(File *f, const void *data, size_t size); 29d06308dfSSiva Chandra Reddy static FileIOResult cookie_read(File *f, void *data, size_t size); 307776fba4SMikhail R. Gadelha static ErrorOr<off_t> cookie_seek(File *f, off_t offset, int whence); 31d06308dfSSiva Chandra Reddy static int cookie_close(File *f); 32d06308dfSSiva Chandra Reddy 33d06308dfSSiva Chandra Reddy public: 34d06308dfSSiva Chandra Reddy CookieFile(void *c, cookie_io_functions_t cops, uint8_t *buffer, 35d06308dfSSiva Chandra Reddy size_t bufsize, File::ModeFlags mode) 36d06308dfSSiva Chandra Reddy : File(&cookie_write, &cookie_read, &CookieFile::cookie_seek, 3775d70b73SSiva Chandra Reddy &cookie_close, buffer, bufsize, 0 /* default buffering mode */, 3875d70b73SSiva Chandra Reddy true /* File owns buffer */, mode), 39d06308dfSSiva Chandra Reddy cookie(c), ops(cops) {} 4019a6dd33SSiva Chandra Reddy }; 4119a6dd33SSiva Chandra Reddy 42d06308dfSSiva Chandra Reddy FileIOResult CookieFile::cookie_write(File *f, const void *data, size_t size) { 4319a6dd33SSiva Chandra Reddy auto cookie_file = reinterpret_cast<CookieFile *>(f); 4419a6dd33SSiva Chandra Reddy if (cookie_file->ops.write == nullptr) 4519a6dd33SSiva Chandra Reddy return 0; 46*91bf0a07SMikhail R. Gadelha return static_cast<size_t>(cookie_file->ops.write( 47*91bf0a07SMikhail R. Gadelha cookie_file->cookie, reinterpret_cast<const char *>(data), size)); 4819a6dd33SSiva Chandra Reddy } 4919a6dd33SSiva Chandra Reddy 50d06308dfSSiva Chandra Reddy FileIOResult CookieFile::cookie_read(File *f, void *data, size_t size) { 5119a6dd33SSiva Chandra Reddy auto cookie_file = reinterpret_cast<CookieFile *>(f); 5219a6dd33SSiva Chandra Reddy if (cookie_file->ops.read == nullptr) 5319a6dd33SSiva Chandra Reddy return 0; 54*91bf0a07SMikhail R. Gadelha return static_cast<size_t>(cookie_file->ops.read( 55*91bf0a07SMikhail R. Gadelha cookie_file->cookie, reinterpret_cast<char *>(data), size)); 5619a6dd33SSiva Chandra Reddy } 5719a6dd33SSiva Chandra Reddy 587776fba4SMikhail R. Gadelha ErrorOr<off_t> CookieFile::cookie_seek(File *f, off_t offset, int whence) { 5919a6dd33SSiva Chandra Reddy auto cookie_file = reinterpret_cast<CookieFile *>(f); 6019a6dd33SSiva Chandra Reddy if (cookie_file->ops.seek == nullptr) { 619beb8d11SMichael Jones return Error(EINVAL); 6219a6dd33SSiva Chandra Reddy } 6319a6dd33SSiva Chandra Reddy off64_t offset64 = offset; 6443e52ad5SSiva Chandra Reddy int result = cookie_file->ops.seek(cookie_file->cookie, &offset64, whence); 6543e52ad5SSiva Chandra Reddy if (result == 0) 6643e52ad5SSiva Chandra Reddy return offset64; 6743e52ad5SSiva Chandra Reddy return -1; 6819a6dd33SSiva Chandra Reddy } 6919a6dd33SSiva Chandra Reddy 70d06308dfSSiva Chandra Reddy int CookieFile::cookie_close(File *f) { 7119a6dd33SSiva Chandra Reddy auto cookie_file = reinterpret_cast<CookieFile *>(f); 7219a6dd33SSiva Chandra Reddy if (cookie_file->ops.close == nullptr) 7319a6dd33SSiva Chandra Reddy return 0; 7475d70b73SSiva Chandra Reddy int retval = cookie_file->ops.close(cookie_file->cookie); 7575d70b73SSiva Chandra Reddy if (retval != 0) 7675d70b73SSiva Chandra Reddy return retval; 7775d70b73SSiva Chandra Reddy delete cookie_file; 7875d70b73SSiva Chandra Reddy return 0; 7919a6dd33SSiva Chandra Reddy } 8019a6dd33SSiva Chandra Reddy 8119a6dd33SSiva Chandra Reddy } // anonymous namespace 8219a6dd33SSiva Chandra Reddy 8319a6dd33SSiva Chandra Reddy LLVM_LIBC_FUNCTION(::FILE *, fopencookie, 8419a6dd33SSiva Chandra Reddy (void *cookie, const char *mode, 8519a6dd33SSiva Chandra Reddy cookie_io_functions_t ops)) { 86d06308dfSSiva Chandra Reddy uint8_t *buffer; 87d06308dfSSiva Chandra Reddy { 88d06308dfSSiva Chandra Reddy AllocChecker ac; 89d06308dfSSiva Chandra Reddy buffer = new (ac) uint8_t[File::DEFAULT_BUFFER_SIZE]; 90d06308dfSSiva Chandra Reddy if (!ac) 9119a6dd33SSiva Chandra Reddy return nullptr; 92d06308dfSSiva Chandra Reddy } 93d06308dfSSiva Chandra Reddy AllocChecker ac; 94d06308dfSSiva Chandra Reddy auto *file = new (ac) CookieFile( 95d06308dfSSiva Chandra Reddy cookie, ops, buffer, File::DEFAULT_BUFFER_SIZE, File::mode_flags(mode)); 96d06308dfSSiva Chandra Reddy if (!ac) 97d06308dfSSiva Chandra Reddy return nullptr; 9819a6dd33SSiva Chandra Reddy return reinterpret_cast<::FILE *>(file); 9919a6dd33SSiva Chandra Reddy } 10019a6dd33SSiva Chandra Reddy 1015ff3ff33SPetr Hosek } // namespace LIBC_NAMESPACE_DECL 102