1 /* basic fmemopen interface testing.
2    Copyright (C) 2014-2022 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4 
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9 
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14 
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <https://www.gnu.org/licenses/>.  */
18 
19 #include <errno.h>
20 #include <fcntl.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <sys/mman.h>
26 #include <sys/stat.h>
27 #include <sys/types.h>
28 
29 static char *test_file;
30 
31 static void
do_prepare(int argc,char * argv[])32 do_prepare (int argc, char *argv[])
33 {
34   /* Construct the test file name based on ARGV[0], which will be
35      an absolute file name in the build directory.  Don't touch the
36      source directory, which might be read-only.  */
37   if (asprintf (&test_file, "%s.test", argv[0]) < 0)
38     {
39       puts ("asprintf failed\n");
40       exit (EXIT_FAILURE);
41     }
42 }
43 
44 static int
do_test(void)45 do_test (void)
46 {
47   const char blah[] = "BLAH";
48   FILE *fp;
49   char *mmap_data;
50   int ch, fd;
51   struct stat fs;
52   const char *cp;
53 
54   /* setup the physical file, and use it */
55   if ((fp = fopen (test_file, "w+")) == NULL)
56     return 1;
57   if (fwrite (blah, 1, strlen (blah), fp) != strlen (blah))
58     {
59       fclose (fp);
60       return 2;
61     }
62 
63   rewind (fp);
64   printf ("file: ");
65   cp = blah;
66   while ((ch = getc (fp)) != EOF)
67     {
68       fputc (ch, stdout);
69       if (ch != *cp)
70 	{
71 	  printf ("\ncharacter %td: '%c' instead of '%c'\n",
72 		  cp - blah, ch, *cp);
73 	  fclose (fp);
74 	  return 1;
75 	}
76       ++cp;
77     }
78   fputc ('\n', stdout);
79   if (ferror (fp))
80     {
81       puts ("fp: error");
82       fclose (fp);
83       return 1;
84     }
85   if (feof (fp))
86     printf ("fp: EOF\n");
87   else
88     {
89       puts ("not EOF");
90       fclose (fp);
91       return 1;
92     }
93   fclose (fp);
94 
95   /* Now, mmap the file into a buffer, and do that too */
96   if ((fd = open (test_file, O_RDONLY)) == -1)
97     {
98       printf ("open (%s, O_RDONLY) failed\n", test_file);
99       return 3;
100     }
101   if (fstat (fd, &fs) == -1)
102     {
103       printf ("stat (%i)\n", fd);
104       return 4;
105     }
106 
107   if ((mmap_data = (char *) mmap (NULL, fs.st_size, PROT_READ,
108 				  MAP_SHARED, fd, 0)) == MAP_FAILED)
109     {
110       printf ("mmap (NULL, %zu, PROT_READ, MAP_SHARED, %i, 0) failed\n",
111 	      (size_t) fs.st_size, fd);
112       return 5;
113     }
114 
115   if ((fp = fmemopen (mmap_data, fs.st_size, "r")) == NULL)
116     {
117       printf ("fmemopen (%p, %zu) failed\n", mmap_data, (size_t) fs.st_size);
118       return 1;
119     }
120 
121   printf ("mem: ");
122   cp = blah;
123   while ((ch = getc (fp)) != EOF)
124     {
125       fputc (ch, stdout);
126       if (ch != *cp)
127 	{
128 	  printf ("%td character: '%c' instead of '%c'\n",
129 		  cp - blah, ch, *cp);
130 	  fclose (fp);
131 	  return 1;
132 	}
133       ++cp;
134     }
135 
136   fputc ('\n', stdout);
137 
138   if (ferror (fp))
139     {
140       puts ("fp: error");
141       fclose (fp);
142       return 1;
143     }
144   if (feof (fp))
145     printf ("fp: EOF\n");
146   else
147     {
148       puts ("not EOF");
149       fclose (fp);
150       return 1;
151     }
152 
153   fclose (fp);
154 
155   munmap (mmap_data, fs.st_size);
156 
157   unlink (test_file);
158   free (test_file);
159 
160   return 0;
161 }
162 
163 #define PREPARE(argc, argv) do_prepare (argc, argv)
164 #define TEST_FUNCTION       do_test ()
165 #include "../test-skeleton.c"
166