2 ** Copyright (C) 2001-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
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.
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.
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.
30 #if (HAVE_DECL_S_IRGRP == 0)
31 #include <sf_unistd.h>
37 #include <sys/types.h>
40 #define SIGNED_SIZEOF(x) ((int) sizeof (x))
43 #if defined (__CYGWIN__) || defined (__EMX__)
48 typedef struct stat STATBUF
;
51 static char dir_cmd
[] = "ls -l" ;
53 #elif (defined (WIN32) || defined (_WIN32))
55 #define LSEEK _lseeki64
56 #define FSTAT _fstati64
58 typedef struct _stati64 STATBUF
;
59 typedef __int64 INT64
;
61 static char dir_cmd
[] = "dir" ;
68 typedef struct stat STATBUF
;
69 typedef sf_count_t INT64
;
72 static char dir_cmd
[] = "ls -l" ;
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) ;
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"
93 show_stat_fstat_error () ;
94 write_to_closed_file () ;
102 show_fstat_error (void)
103 { static const char *filename
= "fstat.dat" ;
104 static char data
[256] ;
107 int fd
, mode
, flags
;
109 if (sizeof (statbuf
.st_size
) != sizeof (INT64
))
110 { printf ("\n\nLine %d: Error, sizeof (statbuf.st_size) != 8.\n\n", __LINE__
) ;
114 puts ("\n64 bit fstat() test.\n--------------------") ;
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
)) ;
123 assert (write (fd
, data
, sizeof (data
)) > 0) ;
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
)) ;
133 LSEEK (fd
, 0, SEEK_END
) ;
134 assert (write (fd
, data
, sizeof (data
)) > 0) ;
136 printf ("2) Now use system (\"%s %s\") to show the file length.\n\n", dir_cmd
, filename
) ;
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
)) ;
144 assert (system (data
) >= 0) ;
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
)) ;
153 printf ("4) According to fstat(), the file length is %ld, ", (long) statbuf
.st_size
) ;
157 if (statbuf
.st_size
!= 2 * sizeof (data
))
158 printf ("but thats just plain ***WRONG***.\n\n") ;
160 { printf ("which is correct.\n\n") ;
164 } /* show_fstat_error */
167 show_lseek_error (void)
168 { static const char *filename
= "fstat.dat" ;
169 static char data
[256] ;
172 int fd
, mode
, flags
;
174 puts ("\n64 bit lseek() test.\n--------------------") ;
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
)) ;
183 assert (write (fd
, data
, sizeof (data
)) > 0) ;
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
)) ;
194 LSEEK (fd
, 0, SEEK_END
) ;
195 assert (write (fd
, data
, sizeof (data
)) > 0) ;
197 printf ("2) Now use system (\"%s %s\") to show the file length.\n\n", dir_cmd
, filename
) ;
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
)) ;
205 assert (system (data
) >= 0) ;
208 printf ("3) Now use lseek() to go to the end of the file.\n") ;
209 retval
= LSEEK (fd
, 0, SEEK_END
) ;
211 printf ("4) We are now at position %ld, ", (long) retval
) ;
215 if (retval
!= 2 * sizeof (data
))
216 printf ("but thats just plain ***WRONG***.\n\n") ;
218 { printf ("which is correct.\n\n") ;
222 } /* show_lseek_error */
225 show_stat_fstat_error (void)
226 { static const char *filename
= "stat_fstat.dat" ;
227 static char data
[256] ;
229 int fd
, mode
, flags
;
230 int stat_size
, fstat_size
;
233 /* Known to fail on WinXP. */
234 puts ("\nstat/fstat test.\n----------------") ;
236 printf ("0) Create a file and write %d bytes.\n", SIGNED_SIZEOF (data
)) ;
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
)) ;
245 assert (write (fd
, data
, sizeof (data
)) > 0) ;
247 printf ("1) Now call stat and fstat on the file and retreive the file lengths.\n") ;
249 if (stat (filename
, &buf
) != 0)
250 { printf ("\n\nLine %d: stat() failed : %s\n\n", __LINE__
, strerror (errno
)) ;
253 stat_size
= buf
.st_size
;
255 if (fstat (fd
, &buf
) != 0)
256 { printf ("\n\nLine %d: fstat() failed : %s\n\n", __LINE__
, strerror (errno
)) ;
259 fstat_size
= buf
.st_size
;
261 printf ("2) Size returned by stat and fstat is %d and %d, ", stat_size
, fstat_size
) ;
264 if (stat_size
== 0 || stat_size
!= fstat_size
)
265 printf ("but thats just plain ***WRONG***.\n\n") ;
267 printf ("which is correct.\n\n") ;
275 } /* show_stat_fstat_error */
279 write_to_closed_file (void)
280 { const char * filename
= "closed_write_test.txt" ;
285 puts ("\nWrite to closed file test.\n--------------------------") ;
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
)) ;
293 printf ("1) Now we grab the file descriptor fileno().\n") ;
296 printf ("2) Write some text via the file descriptor.\n") ;
297 assert (write (fd
, "a\n", 2) > 0) ;
299 printf ("3) Now we close the file using fclose().\n") ;
302 stat (filename
, &buf
) ;
303 printf (" File size is %d bytes.\n", (int) buf
.st_size
) ;
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") ;
309 { printf ("5) Attempting to write to a closed file should have failed but didn't! *** WRONG ***\n") ;
311 stat (filename
, &buf
) ;
312 printf (" File size is %d bytes.\n", (int) buf
.st_size
) ;
318 } /* write_to_closed_file */