1#include <errno.h>
2#include <stdio.h>
3#include <stdlib.h>
4#include <unistd.h>
5
6
7static char fname[] = "/tmp/rndseek.XXXXXX";
8static char tempdata[65 * 1024];
9
10
11static int do_test (void);
12#define TEST_FUNCTION do_test ()
13
14#include "../test-skeleton.c"
15
16
17static int
18fp_test (const char *name, FILE *fp)
19{
20 int result = 0;
21 int rounds = 10000;
22
23 do
24 {
25 int idx = random () % (sizeof (tempdata) - 2);
26 char ch1;
27 char ch2;
28
29 if (fseek (fp, idx, SEEK_SET) != 0)
30 {
31 printf (format: "%s: %d: fseek failed: %m\n", name, rounds);
32 result = 1;
33 break;
34 }
35
36 ch1 = fgetc_unlocked (fp: fp);
37 ch2 = tempdata[idx];
38 if (ch1 != ch2)
39 {
40 printf (format: "%s: %d: character at index %d not what is expected ('%c' vs '%c')\n",
41 name, rounds, idx, ch1, ch2);
42 result = 1;
43 break;
44 }
45
46 ch1 = fgetc (stream: fp);
47 ch2 = tempdata[idx + 1];
48 if (ch1 != ch2)
49 {
50 printf (format: "%s: %d: character at index %d not what is expected ('%c' vs '%c')\n",
51 name, rounds, idx + 1, ch1, ch2);
52 result = 1;
53 break;
54 }
55 }
56 while (--rounds > 0);
57
58 fclose (fp);
59
60 return result;
61}
62
63
64static int
65do_test (void)
66{
67 int fd;
68 FILE *fp;
69 size_t i;
70 int result;
71
72 fd = mkstemp (template: fname);
73 if (fd == -1)
74 {
75 printf (format: "cannot open temporary file: %m\n");
76 return 1;
77 }
78 /* Make sure the file gets removed. */
79 add_temp_file (name: fname);
80
81 /* Repeatability demands this. */
82 srandom (seed: 42);
83
84 /* First create some temporary data. */
85 for (i = 0; i < sizeof (tempdata); ++i)
86 tempdata[i] = 'a' + random () % 26;
87
88 /* Write this data to a file. */
89 if (TEMP_FAILURE_RETRY (write (fd, tempdata, sizeof (tempdata)))
90 != sizeof (tempdata))
91 {
92 printf (format: "cannot wrote data to temporary file: %m\n");
93 return 1;
94 }
95
96 /* Now try reading the data. */
97 fp = fdopen (dup (fd), "r");
98 if (fp == NULL)
99 {
100 printf (format: "cannot duplicate temporary file descriptor: %m\n");
101 return 1;
102 }
103
104 rewind (fp);
105 for (i = 0; i < sizeof (tempdata); ++i)
106 {
107 int ch0 = fgetc (stream: fp);
108 char ch1 = ch0;
109 char ch2 = tempdata[i];
110
111 if (ch0 == EOF)
112 {
113 puts (s: "premature end of file while reading data");
114 return 1;
115 }
116
117 if (ch1 != ch2)
118 {
119 printf (format: "%zd: '%c' vs '%c'\n", i, ch1, ch2);
120 return 1;
121 }
122 }
123
124 result = fp_test (name: "fdopen(\"r\")", fp);
125
126 fp = fopen (fname, "r");
127 result |= fp_test (name: "fopen(\"r\")", fp);
128
129 fp = fopen64 (filename: fname, modes: "r");
130 result |= fp_test (name: "fopen64(\"r\")", fp);
131
132 /* The "rw" mode will prevent the mmap-using code from being used. */
133 fp = fdopen (fd, "rw");
134 result = fp_test (name: "fdopen(\"rw\")", fp);
135
136 fp = fopen (fname, "rw");
137 result |= fp_test (name: "fopen(\"rw\")", fp);
138
139 fp = fopen64 (filename: fname, modes: "rw");
140 result |= fp_test (name: "fopen64(\"rw\")", fp);
141
142 return result;
143}
144

source code of glibc/stdio-common/tst-rndseek.c