1/* 2 * Copyright (C) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15#include <stdio.h> 16#include <stdlib.h> 17#include <string.h> 18#include <sys/types.h> 19#include <unistd.h> 20#include "test.h" 21 22#define INIT_BUF_SIZE 4 23#define EXPANSION_COEFFICIENT 2 24 25struct cookie 26{ 27 size_t pos; 28 size_t len; 29 size_t size; 30 char *buf; 31}; 32 33ssize_t mread(void *f, char *buf, size_t len) 34{ 35 struct cookie *c = f; 36 if (c->pos > c->len) { 37 return 0; 38 } else if (c->pos + len > c->len) { 39 len = c->len - c->pos; 40 } 41 42 memcpy(buf, c->buf + c->pos, len); 43 c->pos += len; 44 return len; 45} 46 47ssize_t mwrite(void *f, const char *buf, size_t len) 48{ 49 struct cookie *c = f; 50 char *newBuf; 51 if (c->pos + len > c->size) { 52 while (c->pos + len > c->size) { 53 c->size *= EXPANSION_COEFFICIENT; 54 } 55 newBuf = malloc(c->size); 56 if (newBuf == NULL) { 57 return -1; 58 } else { 59 memcpy(newBuf, c->buf, c->len); 60 free(c->buf); 61 c->size = c->pos + len; 62 c->buf = newBuf; 63 } 64 } 65 66 memcpy(c->buf + c->pos, buf, len); 67 c->pos += len; 68 if (c->pos > c->len) { 69 c->len = c->pos; 70 } 71 return len; 72} 73 74int mseek(void *f, off_t *off, int whence) 75{ 76 struct cookie *c = f; 77 off_t newPos; 78 if (whence == SEEK_SET) { 79 newPos = *off; 80 } else if (whence == SEEK_CUR) { 81 newPos = *off + c->pos; 82 } else if (whence == SEEK_END) { 83 newPos = *off + c->len; 84 } else { 85 return -1; 86 } 87 if (newPos < 0) { 88 return -1; 89 } 90 91 c->pos = newPos; 92 *off = newPos; 93 94 return 0; 95} 96 97int mclose(void *f) 98{ 99 struct cookie *c = f; 100 free(c->buf); 101 c->buf = NULL; 102 return 0; 103} 104 105int main(int argc, char *argv[]) 106{ 107 cookie_io_functions_t ioFunc = {.read = mread, .write = mwrite, .seek = mseek, .close = mclose}; 108 FILE *file; 109 struct cookie myc; 110 size_t nread; 111 size_t memberSize = 1; 112 size_t memberNumbers = 2; 113 char buf[50]; 114 myc.buf = malloc(INIT_BUF_SIZE); 115 if (myc.buf == NULL) { 116 t_error("fopencookie malloc failed\n"); 117 return 1; 118 } 119 myc.pos = 0; 120 myc.len = 0; 121 myc.size = INIT_BUF_SIZE; 122 123 file = fopencookie(&myc, "w+", ioFunc); 124 if (file == NULL) { 125 t_error("create fopencookie failed\n"); 126 return 1; 127 } 128 if (fputs("fopencookie", file) == EOF) { 129 t_error("fopencookie fputs failed\n"); 130 return 1; 131 } 132 if (fseek(file, 0, SEEK_SET) == -1) { 133 t_error("fopencookie fseek failed\n"); 134 return 1; 135 } 136 nread = fread(buf, memberSize, memberNumbers, file); 137 if (nread == 0) { 138 if (ferror(file) != 0) { 139 t_error("fopencookie fread failed\n"); 140 return 1; 141 } 142 } 143 fclose(file); 144 return 0; 145}