1570af302Sopenharmony_ci/* Copyright (c) 2021-2022 Huawei Device Co., Ltd. 2570af302Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 3570af302Sopenharmony_ci * you may not use this file except in compliance with the License. 4570af302Sopenharmony_ci * You may obtain a copy of the License at 5570af302Sopenharmony_ci * 6570af302Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 7570af302Sopenharmony_ci * 8570af302Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 9570af302Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 10570af302Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11570af302Sopenharmony_ci * See the License for the specific language governing permissions and 12570af302Sopenharmony_ci * limitations under the License. 13570af302Sopenharmony_ci */ 14570af302Sopenharmony_ci 15570af302Sopenharmony_ci#include "stdio_impl.h" 16570af302Sopenharmony_ci#include <stdlib.h> 17570af302Sopenharmony_ci#include <sys/ioctl.h> 18570af302Sopenharmony_ci#include <sys/stat.h> 19570af302Sopenharmony_ci#include <fcntl.h> 20570af302Sopenharmony_ci#include <errno.h> 21570af302Sopenharmony_ci#include <string.h> 22570af302Sopenharmony_ci#include "libc.h" 23570af302Sopenharmony_ci 24570af302Sopenharmony_cistatic size_t __get_bufsize(int fd) 25570af302Sopenharmony_ci{ 26570af302Sopenharmony_ci struct stat st; 27570af302Sopenharmony_ci size_t buf_size = 0; 28570af302Sopenharmony_ci 29570af302Sopenharmony_ci if (fstat(fd, &st) < 0) { 30570af302Sopenharmony_ci buf_size = BUFSIZ; 31570af302Sopenharmony_ci } else if (st.st_blksize == 0) { 32570af302Sopenharmony_ci buf_size = BUFSIZ; 33570af302Sopenharmony_ci } else { 34570af302Sopenharmony_ci buf_size = st.st_blksize; 35570af302Sopenharmony_ci } 36570af302Sopenharmony_ci 37570af302Sopenharmony_ci return buf_size; 38570af302Sopenharmony_ci} 39570af302Sopenharmony_ci 40570af302Sopenharmony_ciint __falloc_buf(FILE *f) 41570af302Sopenharmony_ci{ 42570af302Sopenharmony_ci /* return if already allocated, or F_NOBUF set */ 43570af302Sopenharmony_ci if (f->buf != NULL || f->buf_size != 0 || f->flags & F_NOBUF) { 44570af302Sopenharmony_ci return 0; 45570af302Sopenharmony_ci } 46570af302Sopenharmony_ci 47570af302Sopenharmony_ci /* Default, base and buf are NULL,and buf_size = 0 */ 48570af302Sopenharmony_ci size_t buf_size = 0; 49570af302Sopenharmony_ci 50570af302Sopenharmony_ci /* get buffer size via file stat */ 51570af302Sopenharmony_ci buf_size = __get_bufsize(f->fd); 52570af302Sopenharmony_ci 53570af302Sopenharmony_ci /* alloc R/W buffer */ 54570af302Sopenharmony_ci f->base = (unsigned char *)malloc(UNGET + buf_size * sizeof(unsigned char)); 55570af302Sopenharmony_ci if (!f->base) { 56570af302Sopenharmony_ci errno = -ENOMEM; 57570af302Sopenharmony_ci return errno; 58570af302Sopenharmony_ci } 59570af302Sopenharmony_ci 60570af302Sopenharmony_ci /* reserve UNGET buffer */ 61570af302Sopenharmony_ci f->buf = f->base + UNGET; 62570af302Sopenharmony_ci f->buf_size = buf_size; 63570af302Sopenharmony_ci 64570af302Sopenharmony_ci return 0; 65570af302Sopenharmony_ci} 66570af302Sopenharmony_ci 67570af302Sopenharmony_ciFILE *__fdopen(int fd, const char *mode) 68570af302Sopenharmony_ci{ 69570af302Sopenharmony_ci FILE *f = NULL; 70570af302Sopenharmony_ci int file_flags = 0; 71570af302Sopenharmony_ci int mode_flags = 0; 72570af302Sopenharmony_ci 73570af302Sopenharmony_ci int flags = syscall(SYS_fcntl, fd, F_GETFL, 0); 74570af302Sopenharmony_ci if (flags == -1) { 75570af302Sopenharmony_ci return NULL; 76570af302Sopenharmony_ci } 77570af302Sopenharmony_ci 78570af302Sopenharmony_ci /* Compute the flags to pass to open() */ 79570af302Sopenharmony_ci mode_flags = __fmodeflags(mode, &file_flags); 80570af302Sopenharmony_ci if (mode_flags < 0) { 81570af302Sopenharmony_ci return NULL; 82570af302Sopenharmony_ci } 83570af302Sopenharmony_ci 84570af302Sopenharmony_ci if (mode_flags & O_CLOEXEC) { 85570af302Sopenharmony_ci __syscall(SYS_fcntl, fd, F_SETFD, FD_CLOEXEC); 86570af302Sopenharmony_ci } 87570af302Sopenharmony_ci 88570af302Sopenharmony_ci if (mode_flags & O_APPEND) { 89570af302Sopenharmony_ci flags = __syscall(SYS_fcntl, fd, F_GETFL); 90570af302Sopenharmony_ci if (!(flags & O_APPEND)) 91570af302Sopenharmony_ci __syscall(SYS_fcntl, fd, F_SETFL, flags | O_APPEND); 92570af302Sopenharmony_ci } 93570af302Sopenharmony_ci 94570af302Sopenharmony_ci f = __fdopenx(fd, file_flags); 95570af302Sopenharmony_ci if (f) { 96570af302Sopenharmony_ci return f; 97570af302Sopenharmony_ci } 98570af302Sopenharmony_ci 99570af302Sopenharmony_ci return NULL; 100570af302Sopenharmony_ci} 101570af302Sopenharmony_ciweak_alias(__fdopen, fdopen); 102570af302Sopenharmony_ci 103570af302Sopenharmony_ciFILE *__fdopenx(int fd, int flags) 104570af302Sopenharmony_ci{ 105570af302Sopenharmony_ci FILE *f = 0; 106570af302Sopenharmony_ci struct winsize wsz; 107570af302Sopenharmony_ci 108570af302Sopenharmony_ci /* Allocate FILE or fail */ 109570af302Sopenharmony_ci if (!(f = __ofl_alloc())) { 110570af302Sopenharmony_ci return NULL; 111570af302Sopenharmony_ci } 112570af302Sopenharmony_ci 113570af302Sopenharmony_ci /* Zero-fill only the struct, not the buffer */ 114570af302Sopenharmony_ci memset(f, 0, sizeof *f); 115570af302Sopenharmony_ci 116570af302Sopenharmony_ci f->flags = flags; 117570af302Sopenharmony_ci f->fd = fd; 118570af302Sopenharmony_ci 119570af302Sopenharmony_ci /* Activate line buffered mode for terminals */ 120570af302Sopenharmony_ci f->lbf = EOF; 121570af302Sopenharmony_ci if (!(f->flags & F_NOWR) && !__syscall(SYS_ioctl, fd, TIOCGWINSZ, &wsz)) { 122570af302Sopenharmony_ci f->lbf = '\n'; 123570af302Sopenharmony_ci } 124570af302Sopenharmony_ci 125570af302Sopenharmony_ci#ifndef __LITEOS__ 126570af302Sopenharmony_ci /* set file tag in fdtable, FILE type */ 127570af302Sopenharmony_ci fdsan_exchange_owner_tag(fd, 0, __get_file_tag(f)); 128570af302Sopenharmony_ci#endif 129570af302Sopenharmony_ci 130570af302Sopenharmony_ci /* Initialize op ptrs. No problem if some are unneeded. */ 131570af302Sopenharmony_ci f->read = __stdio_read; 132570af302Sopenharmony_ci f->write = __stdio_write; 133570af302Sopenharmony_ci f->seek = __stdio_seek; 134570af302Sopenharmony_ci f->close = __stdio_close; 135570af302Sopenharmony_ci f->readx = __stdio_readx; 136570af302Sopenharmony_ci 137570af302Sopenharmony_ci if (!libc.threaded) { 138570af302Sopenharmony_ci f->lock = -1; 139570af302Sopenharmony_ci } 140570af302Sopenharmony_ci 141570af302Sopenharmony_ci /* Add new FILE to open file list */ 142570af302Sopenharmony_ci return __ofl_add(f); 143570af302Sopenharmony_ci} 144570af302Sopenharmony_ci 145