]>
Commit | Line | Data |
---|---|---|
2482ae43 SP |
1 | /* Verify that ftell returns the correct value after a read and a write on a |
2 | file opened in a+ mode. | |
04277e02 | 3 | Copyright (C) 2014-2019 Free Software Foundation, Inc. |
2482ae43 SP |
4 | This file is part of the GNU C Library. |
5 | ||
6 | The GNU C Library is free software; you can redistribute it and/or | |
7 | modify it under the terms of the GNU Lesser General Public | |
8 | License as published by the Free Software Foundation; either | |
9 | version 2.1 of the License, or (at your option) any later version. | |
10 | ||
11 | The GNU C Library is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | Lesser General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU Lesser General Public | |
17 | License along with the GNU C Library; if not, see | |
18 | <http://www.gnu.org/licenses/>. */ | |
19 | ||
20 | #include <stdio.h> | |
21 | #include <stdlib.h> | |
22 | #include <string.h> | |
23 | #include <errno.h> | |
24 | #include <unistd.h> | |
25 | #include <locale.h> | |
26 | #include <wchar.h> | |
27 | ||
28 | /* data points to either char_data or wide_data, depending on whether we're | |
29 | testing regular file mode or wide mode respectively. Similarly, | |
30 | fputs_func points to either fputs or fputws. data_len keeps track of the | |
31 | length of the current data and file_len maintains the current file | |
32 | length. */ | |
33 | #define BUF_LEN 4 | |
34 | static void *buf; | |
35 | static char char_buf[BUF_LEN]; | |
36 | static wchar_t wide_buf[BUF_LEN]; | |
37 | static const void *data; | |
38 | static const char *char_data = "abcdefghijklmnopqrstuvwxyz"; | |
39 | static const wchar_t *wide_data = L"abcdefghijklmnopqrstuvwxyz"; | |
40 | static size_t data_len; | |
41 | static size_t file_len; | |
42 | ||
43 | typedef int (*fputs_func_t) (const void *data, FILE *fp); | |
44 | fputs_func_t fputs_func; | |
45 | ||
46 | typedef void *(*fgets_func_t) (void *s, int size, FILE *stream); | |
47 | fgets_func_t fgets_func; | |
48 | ||
49 | static int do_test (void); | |
50 | ||
51 | #define TEST_FUNCTION do_test () | |
52 | #include "../test-skeleton.c" | |
53 | ||
54 | static FILE * | |
55 | init_file (const char *filename) | |
56 | { | |
57 | FILE *fp = fopen (filename, "w"); | |
58 | if (fp == NULL) | |
59 | { | |
60 | printf ("fopen: %m\n"); | |
61 | return NULL; | |
62 | } | |
63 | ||
64 | int written = fputs_func (data, fp); | |
65 | ||
66 | if (written == EOF) | |
67 | { | |
68 | printf ("fputs failed to write data\n"); | |
69 | fclose (fp); | |
70 | return NULL; | |
71 | } | |
72 | ||
73 | file_len = data_len; | |
74 | ||
75 | fclose (fp); | |
76 | ||
77 | fp = fopen (filename, "a+"); | |
78 | if (fp == NULL) | |
79 | { | |
80 | printf ("fopen(a+): %m\n"); | |
81 | return NULL; | |
82 | } | |
83 | ||
84 | return fp; | |
85 | } | |
86 | ||
87 | static int | |
88 | do_one_test (const char *filename) | |
89 | { | |
90 | FILE *fp = init_file (filename); | |
91 | ||
92 | if (fp == NULL) | |
93 | return 1; | |
94 | ||
95 | void *ret = fgets_func (buf, BUF_LEN, fp); | |
96 | ||
97 | if (ret == NULL) | |
98 | { | |
99 | printf ("read failed: %m\n"); | |
100 | fclose (fp); | |
101 | return 1; | |
102 | } | |
103 | ||
104 | int written = fputs_func (data, fp); | |
105 | ||
106 | if (written == EOF) | |
107 | { | |
108 | printf ("fputs failed to write data\n"); | |
109 | fclose (fp); | |
110 | return 1; | |
111 | } | |
112 | ||
113 | file_len += data_len; | |
114 | ||
115 | long off = ftell (fp); | |
116 | ||
117 | if (off != file_len) | |
118 | { | |
119 | printf ("Incorrect offset %ld, expected %zu\n", off, file_len); | |
120 | fclose (fp); | |
121 | return 1; | |
122 | } | |
123 | else | |
124 | printf ("Correct offset %ld after write.\n", off); | |
125 | ||
126 | return 0; | |
127 | } | |
128 | ||
129 | /* Run the tests for regular files and wide mode files. */ | |
130 | static int | |
131 | do_test (void) | |
132 | { | |
133 | int ret = 0; | |
134 | char *filename; | |
135 | int fd = create_temp_file ("tst-ftell-append-tmp.", &filename); | |
136 | ||
137 | if (fd == -1) | |
138 | { | |
139 | printf ("create_temp_file: %m\n"); | |
140 | return 1; | |
141 | } | |
142 | ||
143 | close (fd); | |
144 | ||
145 | /* Tests for regular files. */ | |
146 | puts ("Regular mode:"); | |
147 | fputs_func = (fputs_func_t) fputs; | |
148 | fgets_func = (fgets_func_t) fgets; | |
149 | data = char_data; | |
150 | buf = char_buf; | |
151 | data_len = strlen (char_data); | |
152 | ret |= do_one_test (filename); | |
153 | ||
154 | /* Tests for wide files. */ | |
155 | puts ("Wide mode:"); | |
156 | if (setlocale (LC_ALL, "en_US.UTF-8") == NULL) | |
157 | { | |
158 | printf ("Cannot set en_US.UTF-8 locale.\n"); | |
159 | return 1; | |
160 | } | |
161 | fputs_func = (fputs_func_t) fputws; | |
162 | fgets_func = (fgets_func_t) fgetws; | |
163 | data = wide_data; | |
164 | buf = wide_buf; | |
165 | data_len = wcslen (wide_data); | |
166 | ret |= do_one_test (filename); | |
167 | ||
168 | return ret; | |
169 | } |