1 /*
2 * Copyright (c) 2006-2021, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2010-11-17 Bernard first version
9 */
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <finsh.h>
14 #include <sys/errno.h>
15 #include <sys/fcntl.h>
16 #include <sys/stat.h>
17
18 const char* text = "this is a test string\n";
libc_fstat()19 void libc_fstat()
20 {
21 int fd;
22 struct stat s;
23
24 fd = open("/tmp/tt.txt", O_WRONLY | O_CREAT, 0);
25 if (fd < 0)
26 {
27 printf("open failed\n");
28 return;
29 }
30
31 write(fd, text, strlen(text) + 1);
32 printf("begin: %d\n", lseek(fd, 0, SEEK_SET));
33 printf("end: %d\n", lseek(fd, 0, SEEK_END));
34
35 printf("fstat result: %d\n", fstat(fd, &s));
36 close(fd);
37 }
38 FINSH_FUNCTION_EXPORT(libc_fstat, fstat test for libc);
39
libc_lseek()40 void libc_lseek()
41 {
42 int fd;
43
44 fd = open("/tmp/tt.txt", O_WRONLY | O_CREAT, 0);
45 if (fd < 0)
46 {
47 printf("open failed\n");
48 return;
49 }
50
51 write(fd, text, strlen(text) + 1);
52 printf("begin: %d\n", lseek(fd, 0, SEEK_SET));
53 printf("end: %d\n", lseek(fd, 0, SEEK_END));
54 close(fd);
55 }
56 FINSH_FUNCTION_EXPORT(libc_lseek, lseek test for libc);
57
sleep(int tick)58 void sleep(int tick)
59 {
60 rt_thread_delay(tick);
61 }
62
libc_fseek(void)63 int libc_fseek(void)
64 {
65 const char *tmpdir;
66 char *fname;
67 int fd;
68 FILE *fp;
69 const char outstr[] = "hello world!\n";
70 char strbuf[sizeof outstr];
71 char buf[200];
72 struct stat st1;
73 struct stat st2;
74 int result = 0;
75
76 tmpdir = getenv("TMPDIR");
77 if (tmpdir == NULL || tmpdir[0] == '\0')
78 tmpdir = "/tmp";
79
80 asprintf(&fname, "%s/tst-fseek.XXXXXX", tmpdir);
81 if (fname == NULL)
82 {
83 fprintf(stderr, "cannot generate name for temporary file: %s\n",
84 strerror(errno));
85 return 1;
86 }
87
88 /* Create a temporary file. */
89 fd = mkstemp(fname);
90 if (fd == -1)
91 {
92 fprintf(stderr, "cannot open temporary file: %s\n", strerror(errno));
93 return 1;
94 }
95
96 fp = fdopen(fd, "w+");
97 if (fp == NULL)
98 {
99 fprintf(stderr, "cannot get FILE for temporary file: %s\n", strerror(
100 errno));
101 return 1;
102 }
103 setbuffer(fp, strbuf, sizeof(outstr) - 1);
104
105 if (fwrite(outstr, sizeof(outstr) - 1, 1, fp) != 1)
106 {
107 printf("%d: write error\n", __LINE__);
108 result = 1;
109 goto out;
110 }
111
112 /* The EOF flag must be reset. */
113 if (fgetc(fp) != EOF)
114 {
115 printf("%d: managed to read at end of file\n", __LINE__);
116 result = 1;
117 }
118 else if (!feof(fp))
119 {
120 printf("%d: EOF flag not set\n", __LINE__);
121 result = 1;
122 }
123 if (fseek(fp, 0, SEEK_CUR) != 0)
124 {
125 printf("%d: fseek(fp, 0, SEEK_CUR) failed\n", __LINE__);
126 result = 1;
127 }
128 else if (feof(fp))
129 {
130 printf("%d: fseek() didn't reset EOF flag\n", __LINE__);
131 result = 1;
132 }
133
134 /* Do the same for fseeko(). */
135 if (fgetc(fp) != EOF)
136 {
137 printf("%d: managed to read at end of file\n", __LINE__);
138 result = 1;
139 }
140 else if (!feof(fp))
141 {
142 printf("%d: EOF flag not set\n", __LINE__);
143 result = 1;
144 }
145 if (fseeko(fp, 0, SEEK_CUR) != 0)
146 {
147 printf("%d: fseek(fp, 0, SEEK_CUR) failed\n", __LINE__);
148 result = 1;
149 }
150 else if (feof(fp))
151 {
152 printf("%d: fseek() didn't reset EOF flag\n", __LINE__);
153 result = 1;
154 }
155
156 /* Go back to the beginning of the file: absolute. */
157 if (fseek(fp, 0, SEEK_SET) != 0)
158 {
159 printf("%d: fseek(fp, 0, SEEK_SET) failed\n", __LINE__);
160 result = 1;
161 }
162 else if (fflush(fp) != 0)
163 {
164 printf("%d: fflush() failed\n", __LINE__);
165 result = 1;
166 }
167 else if (lseek(fd, 0, SEEK_CUR) != 0)
168 {
169 int pos = lseek(fd, 0, SEEK_CUR);
170 printf("%d: lseek() returned different position, pos %d\n", __LINE__,
171 pos);
172 result = 1;
173 }
174 else if (fread(buf, sizeof(outstr) - 1, 1, fp) != 1)
175 {
176 printf("%d: fread() failed\n", __LINE__);
177 result = 1;
178 }
179 else if (memcmp(buf, outstr, sizeof(outstr) - 1) != 0)
180 {
181 printf("%d: content after fseek(,,SEEK_SET) wrong\n", __LINE__);
182 result = 1;
183 }
184
185 /* Now with fseeko. */
186 if (fseeko(fp, 0, SEEK_SET) != 0)
187 {
188 printf("%d: fseeko(fp, 0, SEEK_SET) failed\n", __LINE__);
189 result = 1;
190 }
191 else if (fflush(fp) != 0)
192 {
193 printf("%d: fflush() failed\n", __LINE__);
194 result = 1;
195 }
196 else if (lseek(fd, 0, SEEK_CUR) != 0)
197 {
198 printf("%d: lseek() returned different position\n", __LINE__);
199 result = 1;
200 }
201 else if (fread(buf, sizeof(outstr) - 1, 1, fp) != 1)
202 {
203 printf("%d: fread() failed\n", __LINE__);
204 result = 1;
205 }
206 else if (memcmp(buf, outstr, sizeof(outstr) - 1) != 0)
207 {
208 printf("%d: content after fseeko(,,SEEK_SET) wrong\n", __LINE__);
209 result = 1;
210 }
211
212 /* Go back to the beginning of the file: relative. */
213 if (fseek(fp, -((int) sizeof(outstr) - 1), SEEK_CUR) != 0)
214 {
215 printf("%d: fseek(fp, 0, SEEK_SET) failed\n", __LINE__);
216 result = 1;
217 }
218 else if (fflush(fp) != 0)
219 {
220 printf("%d: fflush() failed\n", __LINE__);
221 result = 1;
222 }
223 else if (lseek(fd, 0, SEEK_CUR) != 0)
224 {
225 printf("%d: lseek() returned different position\n", __LINE__);
226 result = 1;
227 }
228 else if (fread(buf, sizeof(outstr) - 1, 1, fp) != 1)
229 {
230 printf("%d: fread() failed\n", __LINE__);
231 result = 1;
232 }
233 else if (memcmp(buf, outstr, sizeof(outstr) - 1) != 0)
234 {
235 printf("%d: content after fseek(,,SEEK_SET) wrong\n", __LINE__);
236 result = 1;
237 }
238
239 /* Now with fseeko. */
240 if (fseeko(fp, -((int) sizeof(outstr) - 1), SEEK_CUR) != 0)
241 {
242 printf("%d: fseeko(fp, 0, SEEK_SET) failed\n", __LINE__);
243 result = 1;
244 }
245 else if (fflush(fp) != 0)
246 {
247 printf("%d: fflush() failed\n", __LINE__);
248 result = 1;
249 }
250 else if (lseek(fd, 0, SEEK_CUR) != 0)
251 {
252 printf("%d: lseek() returned different position\n", __LINE__);
253 result = 1;
254 }
255 else if (fread(buf, sizeof(outstr) - 1, 1, fp) != 1)
256 {
257 printf("%d: fread() failed\n", __LINE__);
258 result = 1;
259 }
260 else if (memcmp(buf, outstr, sizeof(outstr) - 1) != 0)
261 {
262 printf("%d: content after fseeko(,,SEEK_SET) wrong\n", __LINE__);
263 result = 1;
264 }
265
266 /* Go back to the beginning of the file: from the end. */
267 if (fseek(fp, -((int) sizeof(outstr) - 1), SEEK_END) != 0)
268 {
269 printf("%d: fseek(fp, 0, SEEK_SET) failed\n", __LINE__);
270 result = 1;
271 }
272 else if (fflush(fp) != 0)
273 {
274 printf("%d: fflush() failed\n", __LINE__);
275 result = 1;
276 }
277 else if (lseek(fd, 0, SEEK_CUR) != 0)
278 {
279 printf("%d: lseek() returned different position\n", __LINE__);
280 result = 1;
281 }
282 else if (fread(buf, sizeof(outstr) - 1, 1, fp) != 1)
283 {
284 printf("%d: fread() failed\n", __LINE__);
285 result = 1;
286 }
287 else if (memcmp(buf, outstr, sizeof(outstr) - 1) != 0)
288 {
289 printf("%d: content after fseek(,,SEEK_SET) wrong\n", __LINE__);
290 result = 1;
291 }
292
293 /* Now with fseeko. */
294 if (fseeko(fp, -((int) sizeof(outstr) - 1), SEEK_END) != 0)
295 {
296 printf("%d: fseeko(fp, 0, SEEK_SET) failed\n", __LINE__);
297 result = 1;
298 }
299 else if (fflush(fp) != 0)
300 {
301 printf("%d: fflush() failed\n", __LINE__);
302 result = 1;
303 }
304 else if (lseek(fd, 0, SEEK_CUR) != 0)
305 {
306 printf("%d: lseek() returned different position\n", __LINE__);
307 result = 1;
308 }
309 else if (fread(buf, sizeof(outstr) - 1, 1, fp) != 1)
310 {
311 printf("%d: fread() failed\n", __LINE__);
312 result = 1;
313 }
314 else if (memcmp(buf, outstr, sizeof(outstr) - 1) != 0)
315 {
316 printf("%d: content after fseeko(,,SEEK_SET) wrong\n", __LINE__);
317 result = 1;
318 }
319
320 if (fwrite(outstr, sizeof(outstr) - 1, 1, fp) != 1)
321 {
322 printf("%d: write error 2\n", __LINE__);
323 result = 1;
324 goto out;
325 }
326
327 if (fwrite(outstr, sizeof(outstr) - 1, 1, fp) != 1)
328 {
329 printf("%d: write error 3\n", __LINE__);
330 result = 1;
331 goto out;
332 }
333
334 if (fwrite(outstr, sizeof(outstr) - 1, 1, fp) != 1)
335 {
336 printf("%d: write error 4\n", __LINE__);
337 result = 1;
338 goto out;
339 }
340
341 if (fwrite(outstr, sizeof(outstr) - 1, 1, fp) != 1)
342 {
343 printf("%d: write error 5\n", __LINE__);
344 result = 1;
345 goto out;
346 }
347
348 if (fputc('1', fp) == EOF || fputc('2', fp) == EOF)
349 {
350 printf("%d: cannot add characters at the end\n", __LINE__);
351 result = 1;
352 goto out;
353 }
354
355 /* Check the access time. */
356 if (fstat(fd, &st1) < 0)
357 {
358 printf("%d: fstat64() before fseeko() failed\n\n", __LINE__);
359 result = 1;
360 }
361 else
362 {
363 sleep(1);
364
365 if (fseek(fp, -(2 + 2 * (sizeof(outstr) - 1)), SEEK_CUR) != 0)
366 {
367 printf("%d: fseek() after write characters failed\n", __LINE__);
368 result = 1;
369 goto out;
370 }
371 else
372 {
373
374 time_t t;
375 /* Make sure the timestamp actually can be different. */
376 sleep(1);
377 t = time(NULL);
378
379 if (fstat(fd, &st2) < 0)
380 {
381 printf("%d: fstat64() after fseeko() failed\n\n", __LINE__);
382 result = 1;
383 }
384 if (st1.st_ctime >= t)
385 {
386 printf("%d: st_ctime not updated\n", __LINE__);
387 result = 1;
388 }
389 if (st1.st_mtime >= t)
390 {
391 printf("%d: st_mtime not updated\n", __LINE__);
392 result = 1;
393 }
394 if (st1.st_ctime >= st2.st_ctime)
395 {
396 printf("%d: st_ctime not changed\n", __LINE__);
397 result = 1;
398 }
399 if (st1.st_mtime >= st2.st_mtime)
400 {
401 printf("%d: st_mtime not changed\n", __LINE__);
402 result = 1;
403 }
404 }
405 }
406
407 if (fread(buf, 1, 2 + 2 * (sizeof(outstr) - 1), fp) != 2 + 2
408 * (sizeof(outstr) - 1))
409 {
410 printf("%d: reading 2 records plus bits failed\n", __LINE__);
411 result = 1;
412 }
413 else if (memcmp(buf, outstr, sizeof(outstr) - 1) != 0 || memcmp(
414 &buf[sizeof(outstr) - 1], outstr, sizeof(outstr) - 1) != 0 || buf[2
415 * (sizeof(outstr) - 1)] != '1' || buf[2 * (sizeof(outstr) - 1) + 1]
416 != '2')
417 {
418 printf("%d: reading records failed\n", __LINE__);
419 result = 1;
420 }
421 else if (ungetc('9', fp) == EOF)
422 {
423 printf("%d: ungetc() failed\n", __LINE__);
424 result = 1;
425 }
426 else if (fseek(fp, -(2 + 2 * (sizeof(outstr) - 1)), SEEK_END) != 0)
427 {
428 printf("%d: fseek after ungetc failed\n", __LINE__);
429 result = 1;
430 }
431 else if (fread(buf, 1, 2 + 2 * (sizeof(outstr) - 1), fp) != 2 + 2
432 * (sizeof(outstr) - 1))
433 {
434 printf("%d: reading 2 records plus bits failed\n", __LINE__);
435 result = 1;
436 }
437 else if (memcmp(buf, outstr, sizeof(outstr) - 1) != 0 || memcmp(
438 &buf[sizeof(outstr) - 1], outstr, sizeof(outstr) - 1) != 0 || buf[2
439 * (sizeof(outstr) - 1)] != '1')
440 {
441 printf("%d: reading records for the second time failed\n", __LINE__);
442 result = 1;
443 }
444 else if (buf[2 * (sizeof(outstr) - 1) + 1] == '9')
445 {
446 printf("%d: unget character not ignored\n", __LINE__);
447 result = 1;
448 }
449 else if (buf[2 * (sizeof(outstr) - 1) + 1] != '2')
450 {
451 printf("%d: unget somehow changed character\n", __LINE__);
452 result = 1;
453 }
454
455 fclose(fp);
456
457 fp = fopen(fname, "r");
458 if (fp == NULL)
459 {
460 printf("%d: fopen() failed\n\n", __LINE__);
461 result = 1;
462 }
463 else if (fstat(fileno(fp), &st1) < 0)
464 {
465 printf("%d: fstat64() before fseeko() failed\n\n", __LINE__);
466 result = 1;
467 }
468 else if (fseeko(fp, 0, SEEK_END) != 0)
469 {
470 printf("%d: fseeko(fp, 0, SEEK_END) failed\n", __LINE__);
471 result = 1;
472 }
473 else if (ftello(fp) != st1.st_size)
474 {
475 printf("%d: fstat64 st_size %zd ftello %zd\n", __LINE__,
476 (size_t) st1.st_size, (size_t) ftello(fp));
477 result = 1;
478 }
479 else
480 printf("%d: SEEK_END works\n", __LINE__);
481 if (fp != NULL)
482 fclose(fp);
483
484 fp = fopen(fname, "r");
485 if (fp == NULL)
486 {
487 printf("%d: fopen() failed\n\n", __LINE__);
488 result = 1;
489 }
490 else if (fstat(fileno(fp), &st1) < 0)
491 {
492 printf("%d: fstat64() before fgetc() failed\n\n", __LINE__);
493 result = 1;
494 }
495 else if (fgetc(fp) == EOF)
496 {
497 printf("%d: fgetc() before fseeko() failed\n\n", __LINE__);
498 result = 1;
499 }
500 else if (fseeko(fp, 0, SEEK_END) != 0)
501 {
502 printf("%d: fseeko(fp, 0, SEEK_END) failed\n", __LINE__);
503 result = 1;
504 }
505 else if (ftello(fp) != st1.st_size)
506 {
507 printf("%d: fstat64 st_size %zd ftello %zd\n", __LINE__,
508 (size_t) st1.st_size, (size_t) ftello(fp));
509 result = 1;
510 }
511 else
512 printf("%d: SEEK_END works\n", __LINE__);
513 if (fp != NULL)
514 fclose(fp);
515
516 out: unlink(fname);
517
518 return result;
519 }
520 FINSH_FUNCTION_EXPORT(libc_fseek, lseek test for libc);
521