1 /*	$OpenBSD: fmemopentest.c,v 1.4 2020/08/17 16:17:39 millert Exp $ */
2 
3 /*
4  * Copyright (c) 2011 Martin Pieuchot <mpi@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <err.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24 
25 int
simpletest(void)26 simpletest(void)
27 {
28 	FILE	*s1, *s2;
29 	char	 string[] = "fmemopen test string!";
30 	char	 buffer[1024], *buf = NULL;
31 	size_t	 len;
32 	int	 c, failures = 0;
33 
34 	s1 = fmemopen(string, strlen(string) + 1, "r");
35 	if (s1 == NULL) {
36 		warn("unable to open a stream s1");
37 		return (1);
38 	}
39 
40 	s2 = fmemopen(buf, 22, "w+");
41 	if (s2 == NULL) {
42 		warn("unable to create a stream s2");
43 		fclose(s1);
44 		return (1);
45 	}
46 
47 	while ((c = fgetc(s1)) != EOF)
48 		fputc(c, s2);
49 
50 	if (ftell(s2) != strlen(string) + 1) {
51 		warnx("failed copy test (1)");
52 		failures++;
53 	}
54 	fclose(s1);
55 
56 	fseek(s2, 0, SEEK_SET);
57 	if (ftell(s2) != 0) {
58 		warnx("failed seek test (2)");
59 		failures++;
60 	}
61 
62 	len = fread(buffer, 1, sizeof(buffer) - 1, s2);
63 	if (len != strlen(string) + 1) {
64 		warnx("failed read test (3) %zu != %zu",
65 		    len, strlen(string) + 1);
66 		failures++;
67 	}
68 
69 	return (failures);
70 }
71 
72 int
appendtest(const char * mode)73 appendtest(const char *mode)
74 {
75 	FILE	*s1;
76 	char	 string[] = "hello\0 test number 2";
77 	char	 buffer[256];
78 	size_t	 len;
79 	int	 failures = 0;
80 
81 	s1 = fmemopen(string, 19, mode);
82 	if (s1 == NULL)
83 		return (1);
84 
85 	fseek(s1, 0, SEEK_SET);
86 	if (ftell(s1) != 0) {
87 		warnx("failed seek test [%s] (4)", mode);
88 		failures++;
89 	}
90 
91 	/* write should append even though seek position is 0 */
92 	len = fwrite(" world", 1, 6, s1);
93 	if (len != 6) {
94 		warnx("failed write test [%s] (5)", mode);
95 		failures++;
96 	}
97 
98 	if (ftell(s1) != strlen("hello world")) {
99 		warnx("failed seek test [%s] (6)", mode);
100 		failures++;
101 	}
102 
103 	if (mode[1] == '+') {
104 		fseek(s1, 0, SEEK_SET);
105 		len = fread(buffer, 1, sizeof(buffer) - 1, s1);
106 		if (len == 0 || strncmp(string, buffer, len)) {
107 			warnx("failed compare test [%s] (7)", mode);
108 			failures++;
109 		}
110 	}
111 
112 	if (strcmp(string, "hello world")) {
113 		warnx("failed compare test [%s] (8)", mode);
114 		failures++;
115 	}
116 
117 	if (strcmp(string + strlen(string) + 1, "number 2")) {
118 		warnx("failed compare test [%s] (9)", mode);
119 		failures++;
120 	}
121 
122 	return (failures);
123 }
124 
125 int
updatetest(void)126 updatetest(void)
127 {
128 	FILE	*s1;
129 	char	 string[] = "bah, what a day";
130 	char	 buffer[256];
131 	size_t	 len;
132 	int	 failures = 0;
133 
134 	s1 = fmemopen(string, 19, "r+");
135 	if (s1 == NULL)
136 		return (1);
137 
138 	if (ftell(s1) != 0) {
139 		warnx("failed seek test (10)");
140 		failures++;
141 	}
142 
143 	len = fwrite("oh frabjous", 1, 11, s1);
144 	if (len != 11) {
145 		warnx("failed write test (11)");
146 		failures++;
147 	}
148 
149 	fseek(s1, 0, SEEK_SET);
150 	len = fread(buffer, 1, sizeof(buffer) - 1, s1);
151 	if (len == 0 || strncmp(string, buffer, len)) {
152 		warnx("failed compare test (12)");
153 		failures++;
154 	}
155 
156 	if (strcmp(string, "oh frabjous day")) {
157 		warnx("failed compare test (13)");
158 		failures++;
159 	}
160 
161 	return (failures);
162 }
163 
164 int
writetest(const char * mode)165 writetest(const char *mode)
166 {
167 	FILE	*s1;
168 	char	 string[] = "super test number 3";
169 	char	 buffer[256];
170 	size_t	 len, slen;
171 	int	 failures = 0;
172 
173 	slen = strlen(string) + 1;
174 
175 	s1 = fmemopen(string, slen, mode);
176 	if (s1 == NULL)
177 		return (1);
178 
179 	len = fwrite("short", 1, 5, s1);
180 	if (len != strlen("short")) {
181 		warnx("failed write test [%s] (14)", mode);
182 		failures++;
183 	}
184 	fclose(s1);
185 
186 	s1 = fmemopen(string, slen, "r");
187 	if (s1 == NULL) {
188 		warnx("failed open test [%s] (15)", mode);
189 		failures++;
190 	}
191 
192 	len = fread(buffer, 1, sizeof(buffer) - 1, s1);
193 	if (len == 0 || strncmp(string, buffer, len)) {
194 		warnx("failed compare test [%s] (16)", mode);
195 		failures++;
196 	}
197 
198 	if (strcmp(string, "short")) {
199 		warnx("failed compare test [%s] (17)", mode);
200 		failures++;
201 	}
202 
203 	if (strcmp(string + strlen(string) + 1, "test number 3")) {
204 		warnx("failed compare test [%s] (18)", mode);
205 		failures++;
206 	}
207 
208 	return (failures);
209 }
210 
211 int
seektest(void)212 seektest(void)
213 {
214 	FILE	*s1;
215 	char	 string[] = "long string for testing seek";
216 	size_t	 len, slen;
217 	int	 failures = 0;
218 
219 	slen = strlen(string) + 1;
220 
221 	s1 = fmemopen(string, slen, "r");
222 	if (s1 == NULL)
223 		return (1);
224 
225 	if (fseek(s1, 8, SEEK_SET) != 0) {
226 		warnx("failed to fseek. (19)");
227 		failures++;
228 	}
229 
230 	if (ftell(s1) != 8) {
231 		warnx("failed seek test. (20)");
232 		failures++;
233 	}
234 
235 	/* Try to seek backward */
236 	if (fseek(s1, -1, SEEK_CUR) != 0) {
237 		warnx("failed to fseek. (21)");
238 		failures++;
239 	}
240 
241 	if (ftell(s1) != 7) {
242 		warnx("failed seeking backward. (22)");
243 		failures++;
244 	}
245 
246 	return (failures);
247 }
248 
249 int
main(void)250 main(void)
251 {
252 	int	 failures = 0;
253 
254 	failures += simpletest();
255 	failures += appendtest("a");
256 	failures += appendtest("a+");
257 	failures += updatetest();
258 	failures += writetest("w");
259 	failures += writetest("w+");
260 	failures += seektest();
261 
262  	return (failures);
263 }
264