fdwalk should return 0 on an empty directory
[kopensolaris-gnu/glibc.git] / libio / tst-widetext.c
1 /* Test program for the wide character stream functions handling larger
2    amounts of text.
3    Copyright (C) 2000, 2002 Free Software Foundation, Inc.
4    This file is part of the GNU C Library.
5    Contributed by Ulrich Drepper <drepper@cygnus.com>.
6
7    The GNU C Library is free software; you can redistribute it and/or
8    modify it under the terms of the GNU Lesser General Public
9    License as published by the Free Software Foundation; either
10    version 2.1 of the License, or (at your option) any later version.
11
12    The GNU C Library is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    Lesser General Public License for more details.
16
17    You should have received a copy of the GNU Lesser General Public
18    License along with the GNU C Library; if not, write to the Free
19    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20    02111-1307 USA.  */
21
22 #include <assert.h>
23 #include <iconv.h>
24 #include <locale.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <wchar.h>
30
31 /* Approximate size of the file (must be larger).  */
32 #define SIZE 210000
33
34
35 int
36 main (void)
37 {
38   char name[] = "/tmp/widetext.out.XXXXXX";
39   char mbbuf[SIZE];
40   char mb2buf[SIZE];
41   wchar_t wcbuf[SIZE];
42   wchar_t wc2buf[SIZE];
43   size_t mbsize;
44   size_t wcsize;
45   int fd;
46   FILE *fp;
47   size_t n;
48   int res;
49   int status = 0;
50   wchar_t *wcp;
51
52   setlocale (LC_ALL, "de_DE.UTF-8");
53   printf ("locale used: %s\n\n", setlocale (LC_ALL, NULL));
54
55   /* Read the file into memory.  */
56   mbsize = fread (mbbuf, 1, SIZE, stdin);
57   if (mbsize == 0)
58     {
59       printf ("%u: cannot read input file from standard input: %m\n",
60               __LINE__);
61       exit (1);
62     }
63
64    printf ("INFO: input file has %Zd bytes\n", mbsize);
65
66   /* First convert the text to wide characters.  We use iconv here.  */
67   {
68     iconv_t cd;
69     char *inbuf = mbbuf;
70     size_t inleft = mbsize;
71     char *outbuf = (char *) wcbuf;
72     size_t outleft = sizeof (wcbuf);
73     size_t nonr;
74
75     cd = iconv_open ("WCHAR_T", "UTF-8");
76     if (cd == (iconv_t) -1)
77       {
78         printf ("%u: cannot get iconv descriptor for conversion to UCS4\n",
79                 __LINE__);
80         exit (1);
81       }
82
83     /* We must need only one call and there must be no losses.  */
84     nonr = iconv (cd, &inbuf, &inleft, &outbuf, &outleft);
85     if (nonr != 0 && nonr != (size_t) -1)
86       {
87         printf ("%u: iconv performed %Zd nonreversible conversions\n",
88                 __LINE__, nonr);
89         exit (1);
90       }
91
92     if  (nonr == (size_t) -1)
93       {
94         printf ("\
95 %u: iconv returned with %Zd and errno = %m (inleft: %Zd, outleft: %Zd)\n",
96                 __LINE__, nonr, inleft, outleft);
97         exit (1);
98       }
99
100     if (inleft != 0)
101       {
102         printf ("%u: iconv didn't convert all input\n", __LINE__);
103         exit (1);
104       }
105
106     iconv_close (cd);
107
108     if ((sizeof (wcbuf) - outleft) % sizeof (wchar_t) != 0)
109       {
110         printf ("%u: iconv converted not complete wchar_t\n", __LINE__);
111         exit (1);
112       }
113
114     wcsize = (sizeof (wcbuf) - outleft) / sizeof (wchar_t);
115     assert (wcsize + 1 <= SIZE);
116   }
117
118   /* Now that we finished the preparations, run the first test.  We
119      are writing the wide char data out and read it back in.  We write
120      and read single characters.  */
121
122   fd = mkstemp (name);
123   if (fd == -1)
124     {
125       printf ("%u: cannot open temporary file: %m\n", __LINE__);
126       exit (1);
127     }
128
129   unlink (name);
130
131   fp = fdopen (dup (fd), "w");
132   if (fp == NULL)
133     {
134       printf ("%u: fdopen of temp file for writing failed: %m\n", __LINE__);
135       exit (1);
136     }
137
138   for (n = 0; n < wcsize; ++n)
139     {
140       if (fputwc (wcbuf[n], fp) == WEOF)
141         {
142           printf ("%u: fputwc failed: %m\n", __LINE__);
143           exit (1);
144         }
145     }
146
147   res = fclose (fp);
148   if (res != 0)
149     {
150       printf ("%u: fclose after single-character writing failed (%d): %m\n",
151               __LINE__, res);
152       exit (1);
153     }
154
155   lseek (fd, SEEK_SET, 0);
156   fp = fdopen (dup (fd), "r");
157   if (fp == NULL)
158     {
159       printf ("%u: fdopen of temp file for reading failed: %m\n", __LINE__);
160       exit (1);
161     }
162
163   for (n = 0; n < wcsize; ++n)
164     {
165       wint_t wch = fgetwc (fp);
166       if (wch == WEOF)
167         {
168           printf ("%u: fgetwc failed (idx %Zd): %m\n", __LINE__, n);
169           exit (1);
170         }
171       wc2buf[n] = wch;
172     }
173
174   /* There should be nothing else.  */
175   if (fgetwc (fp) != WEOF)
176     {
177       printf ("%u: too many characters available with fgetwc\n", __LINE__);
178       status = 1;
179     }
180   else if (wmemcmp (wcbuf, wc2buf, wcsize) != 0)
181     {
182       printf ("%u: buffer read with fgetwc differs\n", __LINE__);
183       status = 1;
184     }
185
186   res = fclose (fp);
187   if (res != 0)
188     {
189       printf ("%u: fclose after single-character reading failed (%d): %m\n",
190               __LINE__, res);
191       exit (1);
192     }
193
194   /* Just make sure there are no two errors which hide each other, read the
195      file using the `char' functions.  */
196
197   lseek (fd, SEEK_SET, 0);
198   fp = fdopen (fd, "r");
199   if (fp == NULL)
200     {
201       printf ("%u: fdopen of temp file for reading failed: %m\n", __LINE__);
202       exit (1);
203     }
204
205   if (fread (mb2buf, 1, mbsize, fp) != mbsize)
206     {
207       printf ("%u: cannot read all of the temp file\n", __LINE__);
208       status = 1;
209     }
210   else
211     {
212       /* Make sure there is nothing left.  */
213       if (fgetc (fp) != EOF)
214         {
215           printf ("%u: more input available\n", __LINE__);
216           status = 1;
217         }
218
219       if (memcmp (mb2buf, mbbuf, mbsize) != 0)
220         {
221           printf ("%u: buffer written with fputwc differs\n", __LINE__);
222           status = 1;
223         }
224     }
225
226   res = fclose (fp);
227   if (res != 0)
228     {
229       printf ("%u: fclose after single-character reading failed (%d): %m\n",
230               __LINE__, res);
231       exit (1);
232     }
233
234   /* Now to reading and writing line-wise.  */
235
236   fd = mkstemp (strcpy (name, "/tmp/widetext.out.XXXXXX"));
237   if (fd == -1)
238     {
239       printf ("%u: cannot open temporary file: %m\n", __LINE__);
240       exit (1);
241     }
242
243   unlink (name);
244
245   fp = fdopen (dup (fd), "w");
246   if (fp == NULL)
247     {
248       printf ("%u: fdopen of temp file for writing failed: %m\n", __LINE__);
249       exit (1);
250     }
251
252   for (wcp = wcbuf; wcp < &wcbuf[wcsize]; )
253     {
254       wchar_t *wendp = wcschr (wcp, L'\n');
255
256       if (wendp != NULL)
257         {
258           /* Temporarily NUL terminate the line.  */
259           wchar_t save = wendp[1];
260           wendp[1] = L'\0';
261
262           fputws (wcp, fp);
263
264           wendp[1] = save;
265           wcp = &wendp[1];
266         }
267       else
268         {
269           fputws (wcp, fp);
270           wcp = wcschr (wcp, L'\0');
271           assert (wcp == &wcbuf[wcsize]);
272         }
273     }
274
275   res = fclose (fp);
276   if (res != 0)
277     {
278       printf ("%u: fclose after line-wise writing failed (%d): %m\n",
279               __LINE__, res);
280       exit (1);
281     }
282
283   lseek (fd, SEEK_SET, 0);
284   fp = fdopen (dup (fd), "r");
285   if (fp == NULL)
286     {
287       printf ("%u: fdopen of temp file for reading failed: %m\n", __LINE__);
288       exit (1);
289     }
290
291   for (wcp = wc2buf; wcp < &wc2buf[wcsize]; )
292     {
293       if (fgetws (wcp, &wc2buf[wcsize] - wcp + 1, fp) == NULL)
294         {
295           printf ("%u: short read using fgetws (only %Zd of %Zd)\n",
296                   __LINE__, wcp - wc2buf, wcsize);
297           status = 1;
298           break;
299         }
300       wcp = wcschr (wcp, L'\0');
301     }
302
303   if (wcp > &wc2buf[wcsize])
304     {
305       printf ("%u: fgetws read too much\n", __LINE__);
306       status = 1;
307     }
308   else if (fgetwc (fp) != WEOF)
309     {
310       /* There should be nothing else.  */
311       printf ("%u: too many characters available with fgetws\n", __LINE__);
312       status = 1;
313     }
314
315   if (wcp >= &wc2buf[wcsize] && wmemcmp (wcbuf, wc2buf, wcsize) != 0)
316     {
317       printf ("%u: buffer read with fgetws differs\n", __LINE__);
318       status = 1;
319     }
320
321   res = fclose (fp);
322   if (res != 0)
323     {
324       printf ("%u: fclose after single-character reading failed (%d): %m\n",
325               __LINE__, res);
326       exit (1);
327     }
328
329   /* Just make sure there are no two errors which hide each other, read the
330      file using the `char' functions.  */
331
332   lseek (fd, SEEK_SET, 0);
333   fp = fdopen (fd, "r");
334   if (fp == NULL)
335     {
336       printf ("%u: fdopen of temp file for reading failed: %m\n", __LINE__);
337       exit (1);
338     }
339
340   if (fread (mb2buf, 1, mbsize, fp) != mbsize)
341     {
342       printf ("%u: cannot read all of the temp file\n", __LINE__);
343       status = 1;
344     }
345   else
346     {
347       /* Make sure there is nothing left.  */
348       if (fgetc (fp) != EOF)
349         {
350           printf ("%u: more input available\n", __LINE__);
351           status = 1;
352         }
353
354       if (memcmp (mb2buf, mbbuf, mbsize) != 0)
355         {
356           printf ("%u: buffer written with fputws differs\n", __LINE__);
357           status = 1;
358         }
359     }
360
361   res = fclose (fp);
362   if (res != 0)
363     {
364       printf ("%u: fclose after single-character reading failed (%d): %m\n",
365               __LINE__, res);
366       exit (1);
367     }
368
369   return status;
370 }