• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 ** Copyright (C) 2001-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
3 **
4 ** This program is free software; you can redistribute it and/or modify
5 ** it under the terms of the GNU General Public License as published by
6 ** the Free Software Foundation; either version 2 of the License, or
7 ** (at your option) any later version.
8 **
9 ** This program is distributed in the hope that it will be useful,
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 ** GNU General Public License for more details.
13 **
14 ** You should have received a copy of the GNU General Public License
15 ** along with this program; if not, write to the Free Software
16 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18 
19 #include "sfconfig.h"
20 #include "sndfile.h"
21 
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <assert.h>
25 
26 #if HAVE_UNISTD_H
27 #include <unistd.h>
28 #endif
29 
30 #if (HAVE_DECL_S_IRGRP == 0)
31 #include <sf_unistd.h>
32 #endif
33 
34 #include <string.h>
35 #include <fcntl.h>
36 #include <errno.h>
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 
40 #define SIGNED_SIZEOF(x)	((int) sizeof (x))
41 
42 /* EMX is OS/2. */
43 #if defined (__CYGWIN__) || defined (__EMX__)
44 
45 	#define		LSEEK	lseek
46 	#define		FSTAT	fstat
47 
48 	typedef		struct stat			STATBUF ;
49 	typedef		off_t				INT64 ;
50 
51 	static char dir_cmd [] = "ls -l" ;
52 
53 #elif (defined (WIN32) || defined (_WIN32))
54 
55 	#define		LSEEK	_lseeki64
56 	#define		FSTAT	_fstati64
57 
58 	typedef		struct _stati64		STATBUF ;
59 	typedef		__int64				INT64 ;
60 
61 	static char dir_cmd [] = "dir" ;
62 
63 #else
64 
65 	#define		LSEEK	lseek
66 	#define		FSTAT	fstat
67 
68 	typedef		struct stat		STATBUF ;
69 	typedef		sf_count_t		INT64 ;
70 
71 	#define		O_BINARY	0
72 	static char dir_cmd [] = "ls -l" ;
73 
74 #endif
75 
76 static void show_fstat_error (void) ;
77 static void show_lseek_error (void) ;
78 static void show_stat_fstat_error (void) ;
79 static void write_to_closed_file (void) ;
80 
81 int
main(void)82 main (void)
83 {
84 	puts ("\n\n\n\n"
85 		"This program shows up errors in the Win32 implementation of\n"
86 		"a couple of POSIX API functions on some versions of windoze.\n"
87 		"It can also be compiled on Linux (which works correctly) and\n"
88 		"other OSes just to provide a sanity check.\n"
89 		) ;
90 
91 	show_fstat_error () ;
92 	show_lseek_error () ;
93 	show_stat_fstat_error () ;
94 	write_to_closed_file () ;
95 
96 	puts ("\n\n") ;
97 
98 	return 0 ;
99 } /* main */
100 
101 static void
show_fstat_error(void)102 show_fstat_error (void)
103 {	static const char *filename = "fstat.dat" ;
104 	static char data [256] ;
105 
106 	STATBUF 	statbuf ;
107 	int fd, mode, flags ;
108 
109 	if (sizeof (statbuf.st_size) != sizeof (INT64))
110 	{	printf ("\n\nLine %d: Error, sizeof (statbuf.st_size) != 8.\n\n", __LINE__) ;
111 		return ;
112 		} ;
113 
114 	puts ("\n64 bit fstat() test.\n--------------------") ;
115 
116 	printf ("0) Create a file, write %d bytes and close it.\n", SIGNED_SIZEOF (data)) ;
117 	mode = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY ;
118 	flags = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ;
119 	if ((fd = open (filename, mode, flags)) < 0)
120 	{	printf ("\n\nLine %d: open() failed : %s\n\n", __LINE__, strerror (errno)) ;
121 		return ;
122 		} ;
123 	assert (write (fd, data, sizeof (data)) > 0) ;
124 	close (fd) ;
125 
126 	printf ("1) Re-open file in read/write mode and write another %d bytes at the end.\n", SIGNED_SIZEOF (data)) ;
127 	mode = O_RDWR | O_BINARY ;
128 	flags = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ;
129 	if ((fd = open (filename, mode, flags)) < 0)
130 	{	printf ("\n\nLine %d: open() failed : %s\n\n", __LINE__, strerror (errno)) ;
131 		return ;
132 		} ;
133 	LSEEK (fd, 0, SEEK_END) ;
134 	assert (write (fd, data, sizeof (data)) > 0) ;
135 
136 	printf ("2) Now use system (\"%s %s\") to show the file length.\n\n", dir_cmd, filename) ;
137 
138 	/* Would use snprintf, but thats not really available on windows. */
139 	memset (data, 0, sizeof (data)) ;
140 	strncpy (data, dir_cmd, sizeof (data) - 1) ;
141 	strncat (data, " ", sizeof (data) - 1 - strlen (data)) ;
142 	strncat (data, filename, sizeof (data) - 1 - strlen (data)) ;
143 
144 	assert (system (data) >= 0) ;
145 	puts ("") ;
146 
147 	printf ("3) Now use fstat() to get the file length.\n") ;
148 	if (FSTAT (fd, &statbuf) != 0)
149 	{	printf ("\n\nLine %d: fstat() returned error : %s\n", __LINE__, strerror (errno)) ;
150 		return ;
151 		} ;
152 
153 	printf ("4) According to fstat(), the file length is %ld, ", (long) statbuf.st_size) ;
154 
155 	close (fd) ;
156 
157 	if (statbuf.st_size != 2 * sizeof (data))
158 		printf ("but thats just plain ***WRONG***.\n\n") ;
159 	else
160 	{	printf ("which is correct.\n\n") ;
161 		unlink (filename) ;
162 		} ;
163 
164 } /* show_fstat_error */
165 
166 static void
show_lseek_error(void)167 show_lseek_error (void)
168 {	static const char *filename = "fstat.dat" ;
169 	static char data [256] ;
170 
171 	INT64	retval ;
172 	int fd, mode, flags ;
173 
174 	puts ("\n64 bit lseek() test.\n--------------------") ;
175 
176 	printf ("0) Create a file, write %d bytes and close it.\n", SIGNED_SIZEOF (data)) ;
177 	mode = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY ;
178 	flags = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ;
179 	if ((fd = open (filename, mode, flags)) < 0)
180 	{	printf ("\n\nLine %d: open() failed : %s\n\n", __LINE__, strerror (errno)) ;
181 		return ;
182 		} ;
183 	assert (write (fd, data, sizeof (data)) > 0) ;
184 	close (fd) ;
185 
186 	printf ("1) Re-open file in read/write mode and write another %d bytes at the end.\n", SIGNED_SIZEOF (data)) ;
187 	mode = O_RDWR | O_BINARY ;
188 	flags = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ;
189 	if ((fd = open (filename, mode, flags)) < 0)
190 	{	printf ("\n\nLine %d: open() failed : %s\n\n", __LINE__, strerror (errno)) ;
191 		return ;
192 		} ;
193 
194 	LSEEK (fd, 0, SEEK_END) ;
195 	assert (write (fd, data, sizeof (data)) > 0) ;
196 
197 	printf ("2) Now use system (\"%s %s\") to show the file length.\n\n", dir_cmd, filename) ;
198 
199 	/* Would use snprintf, but thats not really available on windows. */
200 	memset (data, 0, sizeof (data)) ;
201 	strncpy (data, dir_cmd, sizeof (data) - 1) ;
202 	strncat (data, " ", sizeof (data) - 1 - strlen (data)) ;
203 	strncat (data, filename, sizeof (data) - 1 - strlen (data)) ;
204 
205 	assert (system (data) >= 0) ;
206 	puts ("") ;
207 
208 	printf ("3) Now use lseek() to go to the end of the file.\n") ;
209 	retval = LSEEK (fd, 0, SEEK_END) ;
210 
211 	printf ("4) We are now at position %ld, ", (long) retval) ;
212 
213 	close (fd) ;
214 
215 	if (retval != 2 * sizeof (data))
216 		printf ("but thats just plain ***WRONG***.\n\n") ;
217 	else
218 	{	printf ("which is correct.\n\n") ;
219 		unlink (filename) ;
220 		} ;
221 
222 } /* show_lseek_error */
223 
224 static void
show_stat_fstat_error(void)225 show_stat_fstat_error (void)
226 {	static const char *filename = "stat_fstat.dat" ;
227 	static char data [256] ;
228 
229 	int fd, mode, flags ;
230 	int stat_size, fstat_size ;
231 	struct stat buf ;
232 
233 	/* Known to fail on WinXP. */
234 	puts ("\nstat/fstat test.\n----------------") ;
235 
236 	printf ("0) Create a file and write %d bytes.\n", SIGNED_SIZEOF (data)) ;
237 
238 	mode = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY ;
239 	flags = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ;
240 	if ((fd = open (filename, mode, flags)) < 0)
241 	{	printf ("\n\nLine %d: open() failed : %s\n\n", __LINE__, strerror (errno)) ;
242 		return ;
243 		} ;
244 
245 	assert (write (fd, data, sizeof (data)) > 0) ;
246 
247 	printf ("1) Now call stat and fstat on the file and retreive the file lengths.\n") ;
248 
249 	if (stat (filename, &buf) != 0)
250 	{	printf ("\n\nLine %d: stat() failed : %s\n\n", __LINE__, strerror (errno)) ;
251 		goto error_exit ;
252 		} ;
253 	stat_size = buf.st_size ;
254 
255 	if (fstat (fd, &buf) != 0)
256 	{	printf ("\n\nLine %d: fstat() failed : %s\n\n", __LINE__, strerror (errno)) ;
257 		goto error_exit ;
258 		} ;
259 	fstat_size = buf.st_size ;
260 
261 	printf ("2) Size returned by stat and fstat is %d and %d, ", stat_size, fstat_size) ;
262 
263 
264 	if (stat_size == 0 || stat_size != fstat_size)
265 		printf ("but thats just plain ***WRONG***.\n\n") ;
266 	else
267 		printf ("which is correct.\n\n") ;
268 
269 error_exit :
270 
271 	close (fd) ;
272 	unlink (filename) ;
273 
274 	return ;
275 } /* show_stat_fstat_error */
276 
277 
278 static void
write_to_closed_file(void)279 write_to_closed_file (void)
280 {	const char * filename = "closed_write_test.txt" ;
281 	struct stat buf ;
282 	FILE * file ;
283 	int		fd ;
284 
285 	puts ("\nWrite to closed file test.\n--------------------------") ;
286 
287 	printf ("0) First we open file for write using fopen().\n") ;
288 	if ((file = fopen (filename, "w")) == NULL)
289 	{	printf ("\n\nLine %d: fopen() failed : %s\n\n", __LINE__, strerror (errno)) ;
290 		return ;
291 		} ;
292 
293 	printf ("1) Now we grab the file descriptor fileno().\n") ;
294 	fd = fileno (file) ;
295 
296 	printf ("2) Write some text via the file descriptor.\n") ;
297 	assert (write (fd, "a\n", 2) > 0) ;
298 
299 	printf ("3) Now we close the file using fclose().\n") ;
300 	fclose (file) ;
301 
302 	stat (filename, &buf) ;
303 	printf ("   File size is %d bytes.\n", (int) buf.st_size) ;
304 
305 	printf ("4) Now write more data to the file descriptor which should fail.\n") ;
306 	if (write (fd, "b\n", 2) < 0)
307 		printf ("5) Good, write returned an error code as it should have.\n") ;
308 	else
309 	{	printf ("5) Attempting to write to a closed file should have failed but didn't! *** WRONG ***\n") ;
310 
311 		stat (filename, &buf) ;
312 		printf ("   File size is %d bytes.\n", (int) buf.st_size) ;
313 		} ;
314 
315 	unlink (filename) ;
316 
317 	return ;
318 } /* write_to_closed_file */
319