xref: /illumos-gate/usr/src/test/libc-tests/tests/stdio/ftell_ungetc.c (revision c686756220120076a07be0dcce54be698101a3d1)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2020 Robert Mustacchi
14  */
15 
16 /*
17  * Regression test for illumos#12392. Here, ftello64 didn't correctly handle an
18  * ungetc() in the write path when it was unbuffered.
19  */
20 
21 #include <stdio.h>
22 #include <err.h>
23 #include <stdlib.h>
24 
25 static void
26 check_pos(FILE *f, long pos)
27 {
28 	long l;
29 	off_t off;
30 	off64_t off64;
31 
32 	l = ftell(f);
33 	off = ftello(f);
34 	off64 = ftello64(f);
35 
36 	if (l != pos) {
37 		errx(EXIT_FAILURE, "ftell position mismatched: found %ld, "
38 		    "expected %ld", l, pos);
39 	}
40 
41 	if (off != pos) {
42 		errx(EXIT_FAILURE, "ftello position mismatched: found %ld, "
43 		    "expected %ld", off, pos);
44 	}
45 
46 	if (off64 != pos) {
47 		errx(EXIT_FAILURE, "ftello64 position mismatched: found %ld, "
48 		    "expected %ld", off64, pos);
49 	}
50 }
51 
52 static void
53 check_one(FILE *f)
54 {
55 	if (fputc('a', f) != 'a') {
56 		err(EXIT_FAILURE, "failed to write character");
57 	}
58 	check_pos(f, 1);
59 
60 	if (ungetc('b', f) != 'b') {
61 		err(EXIT_FAILURE, "failed to unget character");
62 	}
63 	check_pos(f, 0);
64 }
65 
66 int
67 main(void)
68 {
69 	FILE *f;
70 
71 	f = tmpfile();
72 	if (f == NULL) {
73 		err(EXIT_FAILURE, "failed to create temproary "
74 		    "file");
75 	}
76 
77 	if (setvbuf(f, NULL, _IONBF, 0) != 0) {
78 		err(EXIT_FAILURE, "failed to set non-buffering mode");
79 	}
80 	check_one(f);
81 	if (fclose(f) != 0) {
82 		err(EXIT_FAILURE, "failed to close temporary file");
83 	}
84 
85 	return (0);
86 }
87