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
25 struct cookie
26 {
27 size_t pos;
28 size_t len;
29 size_t size;
30 char *buf;
31 };
32
mread(void *f, char *buf, size_t len)33 ssize_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
mwrite(void *f, const char *buf, size_t len)47 ssize_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
mseek(void *f, off_t *off, int whence)74 int 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
mclose(void *f)97 int mclose(void *f)
98 {
99 struct cookie *c = f;
100 free(c->buf);
101 c->buf = NULL;
102 return 0;
103 }
104
main(int argc, char *argv[])105 int 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 }