1570af302Sopenharmony_ci/* 2570af302Sopenharmony_ci * Copyright (C) 2022 Huawei Device Co., Ltd. 3570af302Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4570af302Sopenharmony_ci * you may not use this file except in compliance with the License. 5570af302Sopenharmony_ci * You may obtain a copy of the License at 6570af302Sopenharmony_ci * 7570af302Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8570af302Sopenharmony_ci * 9570af302Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10570af302Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11570af302Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12570af302Sopenharmony_ci * See the License for the specific language governing permissions and 13570af302Sopenharmony_ci * limitations under the License. 14570af302Sopenharmony_ci */ 15570af302Sopenharmony_ci#include <stdio.h> 16570af302Sopenharmony_ci#include <stdlib.h> 17570af302Sopenharmony_ci#include <string.h> 18570af302Sopenharmony_ci#include <sys/types.h> 19570af302Sopenharmony_ci#include <unistd.h> 20570af302Sopenharmony_ci#include "test.h" 21570af302Sopenharmony_ci 22570af302Sopenharmony_ci#define INIT_BUF_SIZE 4 23570af302Sopenharmony_ci#define EXPANSION_COEFFICIENT 2 24570af302Sopenharmony_ci 25570af302Sopenharmony_cistruct cookie 26570af302Sopenharmony_ci{ 27570af302Sopenharmony_ci size_t pos; 28570af302Sopenharmony_ci size_t len; 29570af302Sopenharmony_ci size_t size; 30570af302Sopenharmony_ci char *buf; 31570af302Sopenharmony_ci}; 32570af302Sopenharmony_ci 33570af302Sopenharmony_cissize_t mread(void *f, char *buf, size_t len) 34570af302Sopenharmony_ci{ 35570af302Sopenharmony_ci struct cookie *c = f; 36570af302Sopenharmony_ci if (c->pos > c->len) { 37570af302Sopenharmony_ci return 0; 38570af302Sopenharmony_ci } else if (c->pos + len > c->len) { 39570af302Sopenharmony_ci len = c->len - c->pos; 40570af302Sopenharmony_ci } 41570af302Sopenharmony_ci 42570af302Sopenharmony_ci memcpy(buf, c->buf + c->pos, len); 43570af302Sopenharmony_ci c->pos += len; 44570af302Sopenharmony_ci return len; 45570af302Sopenharmony_ci} 46570af302Sopenharmony_ci 47570af302Sopenharmony_cissize_t mwrite(void *f, const char *buf, size_t len) 48570af302Sopenharmony_ci{ 49570af302Sopenharmony_ci struct cookie *c = f; 50570af302Sopenharmony_ci char *newBuf; 51570af302Sopenharmony_ci if (c->pos + len > c->size) { 52570af302Sopenharmony_ci while (c->pos + len > c->size) { 53570af302Sopenharmony_ci c->size *= EXPANSION_COEFFICIENT; 54570af302Sopenharmony_ci } 55570af302Sopenharmony_ci newBuf = malloc(c->size); 56570af302Sopenharmony_ci if (newBuf == NULL) { 57570af302Sopenharmony_ci return -1; 58570af302Sopenharmony_ci } else { 59570af302Sopenharmony_ci memcpy(newBuf, c->buf, c->len); 60570af302Sopenharmony_ci free(c->buf); 61570af302Sopenharmony_ci c->size = c->pos + len; 62570af302Sopenharmony_ci c->buf = newBuf; 63570af302Sopenharmony_ci } 64570af302Sopenharmony_ci } 65570af302Sopenharmony_ci 66570af302Sopenharmony_ci memcpy(c->buf + c->pos, buf, len); 67570af302Sopenharmony_ci c->pos += len; 68570af302Sopenharmony_ci if (c->pos > c->len) { 69570af302Sopenharmony_ci c->len = c->pos; 70570af302Sopenharmony_ci } 71570af302Sopenharmony_ci return len; 72570af302Sopenharmony_ci} 73570af302Sopenharmony_ci 74570af302Sopenharmony_ciint mseek(void *f, off_t *off, int whence) 75570af302Sopenharmony_ci{ 76570af302Sopenharmony_ci struct cookie *c = f; 77570af302Sopenharmony_ci off_t newPos; 78570af302Sopenharmony_ci if (whence == SEEK_SET) { 79570af302Sopenharmony_ci newPos = *off; 80570af302Sopenharmony_ci } else if (whence == SEEK_CUR) { 81570af302Sopenharmony_ci newPos = *off + c->pos; 82570af302Sopenharmony_ci } else if (whence == SEEK_END) { 83570af302Sopenharmony_ci newPos = *off + c->len; 84570af302Sopenharmony_ci } else { 85570af302Sopenharmony_ci return -1; 86570af302Sopenharmony_ci } 87570af302Sopenharmony_ci if (newPos < 0) { 88570af302Sopenharmony_ci return -1; 89570af302Sopenharmony_ci } 90570af302Sopenharmony_ci 91570af302Sopenharmony_ci c->pos = newPos; 92570af302Sopenharmony_ci *off = newPos; 93570af302Sopenharmony_ci 94570af302Sopenharmony_ci return 0; 95570af302Sopenharmony_ci} 96570af302Sopenharmony_ci 97570af302Sopenharmony_ciint mclose(void *f) 98570af302Sopenharmony_ci{ 99570af302Sopenharmony_ci struct cookie *c = f; 100570af302Sopenharmony_ci free(c->buf); 101570af302Sopenharmony_ci c->buf = NULL; 102570af302Sopenharmony_ci return 0; 103570af302Sopenharmony_ci} 104570af302Sopenharmony_ci 105570af302Sopenharmony_ciint main(int argc, char *argv[]) 106570af302Sopenharmony_ci{ 107570af302Sopenharmony_ci cookie_io_functions_t ioFunc = {.read = mread, .write = mwrite, .seek = mseek, .close = mclose}; 108570af302Sopenharmony_ci FILE *file; 109570af302Sopenharmony_ci struct cookie myc; 110570af302Sopenharmony_ci size_t nread; 111570af302Sopenharmony_ci size_t memberSize = 1; 112570af302Sopenharmony_ci size_t memberNumbers = 2; 113570af302Sopenharmony_ci char buf[50]; 114570af302Sopenharmony_ci myc.buf = malloc(INIT_BUF_SIZE); 115570af302Sopenharmony_ci if (myc.buf == NULL) { 116570af302Sopenharmony_ci t_error("fopencookie malloc failed\n"); 117570af302Sopenharmony_ci return 1; 118570af302Sopenharmony_ci } 119570af302Sopenharmony_ci myc.pos = 0; 120570af302Sopenharmony_ci myc.len = 0; 121570af302Sopenharmony_ci myc.size = INIT_BUF_SIZE; 122570af302Sopenharmony_ci 123570af302Sopenharmony_ci file = fopencookie(&myc, "w+", ioFunc); 124570af302Sopenharmony_ci if (file == NULL) { 125570af302Sopenharmony_ci t_error("create fopencookie failed\n"); 126570af302Sopenharmony_ci return 1; 127570af302Sopenharmony_ci } 128570af302Sopenharmony_ci if (fputs("fopencookie", file) == EOF) { 129570af302Sopenharmony_ci t_error("fopencookie fputs failed\n"); 130570af302Sopenharmony_ci return 1; 131570af302Sopenharmony_ci } 132570af302Sopenharmony_ci if (fseek(file, 0, SEEK_SET) == -1) { 133570af302Sopenharmony_ci t_error("fopencookie fseek failed\n"); 134570af302Sopenharmony_ci return 1; 135570af302Sopenharmony_ci } 136570af302Sopenharmony_ci nread = fread(buf, memberSize, memberNumbers, file); 137570af302Sopenharmony_ci if (nread == 0) { 138570af302Sopenharmony_ci if (ferror(file) != 0) { 139570af302Sopenharmony_ci t_error("fopencookie fread failed\n"); 140570af302Sopenharmony_ci return 1; 141570af302Sopenharmony_ci } 142570af302Sopenharmony_ci } 143570af302Sopenharmony_ci fclose(file); 144570af302Sopenharmony_ci return 0; 145570af302Sopenharmony_ci}