win32_test.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  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. #include "sfconfig.h"
  19. #include "sndfile.h"
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <assert.h>
  23. #if HAVE_UNISTD_H
  24. #include <unistd.h>
  25. #endif
  26. #if (HAVE_DECL_S_IRGRP == 0)
  27. #include <sf_unistd.h>
  28. #endif
  29. #include <string.h>
  30. #include <fcntl.h>
  31. #include <errno.h>
  32. #include <sys/types.h>
  33. #include <sys/stat.h>
  34. #define SIGNED_SIZEOF(x) ((int) sizeof (x))
  35. /* EMX is OS/2. */
  36. #if defined (__CYGWIN__) || defined (__EMX__)
  37. #define LSEEK lseek
  38. #define FSTAT fstat
  39. typedef struct stat STATBUF ;
  40. typedef off_t INT64 ;
  41. static char dir_cmd [] = "ls -l" ;
  42. #elif (defined (WIN32) || defined (_WIN32))
  43. #define LSEEK _lseeki64
  44. #define FSTAT _fstati64
  45. typedef struct _stati64 STATBUF ;
  46. typedef __int64 INT64 ;
  47. static char dir_cmd [] = "dir" ;
  48. #else
  49. #define LSEEK lseek
  50. #define FSTAT fstat
  51. typedef struct stat STATBUF ;
  52. typedef sf_count_t INT64 ;
  53. #define O_BINARY 0
  54. static char dir_cmd [] = "ls -l" ;
  55. #endif
  56. static void show_fstat_error (void) ;
  57. static void show_lseek_error (void) ;
  58. static void show_stat_fstat_error (void) ;
  59. static void write_to_closed_file (void) ;
  60. int
  61. main (void)
  62. {
  63. puts ("\n\n\n\n"
  64. "This program shows up errors in the Win32 implementation of\n"
  65. "a couple of POSIX API functions on some versions of windoze.\n"
  66. "It can also be compiled on Linux (which works correctly) and\n"
  67. "other OSes just to provide a sanity check.\n"
  68. ) ;
  69. show_fstat_error () ;
  70. show_lseek_error () ;
  71. show_stat_fstat_error () ;
  72. write_to_closed_file () ;
  73. puts ("\n\n") ;
  74. return 0 ;
  75. } /* main */
  76. static void
  77. show_fstat_error (void)
  78. { static const char *filename = "fstat.dat" ;
  79. static char data [256] ;
  80. STATBUF statbuf ;
  81. int fd, mode, flags ;
  82. if (sizeof (statbuf.st_size) != sizeof (INT64))
  83. { printf ("\n\nLine %d: Error, sizeof (statbuf.st_size) != 8.\n\n", __LINE__) ;
  84. return ;
  85. } ;
  86. puts ("\n64 bit fstat() test.\n--------------------") ;
  87. printf ("0) Create a file, write %d bytes and close it.\n", SIGNED_SIZEOF (data)) ;
  88. mode = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY ;
  89. flags = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ;
  90. if ((fd = open (filename, mode, flags)) < 0)
  91. { printf ("\n\nLine %d: open() failed : %s\n\n", __LINE__, strerror (errno)) ;
  92. return ;
  93. } ;
  94. assert (write (fd, data, sizeof (data)) > 0) ;
  95. close (fd) ;
  96. printf ("1) Re-open file in read/write mode and write another %d bytes at the end.\n", SIGNED_SIZEOF (data)) ;
  97. mode = O_RDWR | O_BINARY ;
  98. flags = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ;
  99. if ((fd = open (filename, mode, flags)) < 0)
  100. { printf ("\n\nLine %d: open() failed : %s\n\n", __LINE__, strerror (errno)) ;
  101. return ;
  102. } ;
  103. LSEEK (fd, 0, SEEK_END) ;
  104. assert (write (fd, data, sizeof (data)) > 0) ;
  105. printf ("2) Now use system (\"%s %s\") to show the file length.\n\n", dir_cmd, filename) ;
  106. /* Would use snprintf, but thats not really available on windows. */
  107. memset (data, 0, sizeof (data)) ;
  108. strncpy (data, dir_cmd, sizeof (data) - 1) ;
  109. strncat (data, " ", sizeof (data) - 1 - strlen (data)) ;
  110. strncat (data, filename, sizeof (data) - 1 - strlen (data)) ;
  111. assert (system (data) >= 0) ;
  112. puts ("") ;
  113. printf ("3) Now use fstat() to get the file length.\n") ;
  114. if (FSTAT (fd, &statbuf) != 0)
  115. { printf ("\n\nLine %d: fstat() returned error : %s\n", __LINE__, strerror (errno)) ;
  116. return ;
  117. } ;
  118. printf ("4) According to fstat(), the file length is %ld, ", (long) statbuf.st_size) ;
  119. close (fd) ;
  120. if (statbuf.st_size != 2 * sizeof (data))
  121. printf ("but thats just plain ***WRONG***.\n\n") ;
  122. else
  123. { printf ("which is correct.\n\n") ;
  124. unlink (filename) ;
  125. } ;
  126. } /* show_fstat_error */
  127. static void
  128. show_lseek_error (void)
  129. { static const char *filename = "fstat.dat" ;
  130. static char data [256] ;
  131. INT64 retval ;
  132. int fd, mode, flags ;
  133. puts ("\n64 bit lseek() test.\n--------------------") ;
  134. printf ("0) Create a file, write %d bytes and close it.\n", SIGNED_SIZEOF (data)) ;
  135. mode = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY ;
  136. flags = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ;
  137. if ((fd = open (filename, mode, flags)) < 0)
  138. { printf ("\n\nLine %d: open() failed : %s\n\n", __LINE__, strerror (errno)) ;
  139. return ;
  140. } ;
  141. assert (write (fd, data, sizeof (data)) > 0) ;
  142. close (fd) ;
  143. printf ("1) Re-open file in read/write mode and write another %d bytes at the end.\n", SIGNED_SIZEOF (data)) ;
  144. mode = O_RDWR | O_BINARY ;
  145. flags = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ;
  146. if ((fd = open (filename, mode, flags)) < 0)
  147. { printf ("\n\nLine %d: open() failed : %s\n\n", __LINE__, strerror (errno)) ;
  148. return ;
  149. } ;
  150. LSEEK (fd, 0, SEEK_END) ;
  151. assert (write (fd, data, sizeof (data)) > 0) ;
  152. printf ("2) Now use system (\"%s %s\") to show the file length.\n\n", dir_cmd, filename) ;
  153. /* Would use snprintf, but thats not really available on windows. */
  154. memset (data, 0, sizeof (data)) ;
  155. strncpy (data, dir_cmd, sizeof (data) - 1) ;
  156. strncat (data, " ", sizeof (data) - 1 - strlen (data)) ;
  157. strncat (data, filename, sizeof (data) - 1 - strlen (data)) ;
  158. assert (system (data) >= 0) ;
  159. puts ("") ;
  160. printf ("3) Now use lseek() to go to the end of the file.\n") ;
  161. retval = LSEEK (fd, 0, SEEK_END) ;
  162. printf ("4) We are now at position %ld, ", (long) retval) ;
  163. close (fd) ;
  164. if (retval != 2 * sizeof (data))
  165. printf ("but thats just plain ***WRONG***.\n\n") ;
  166. else
  167. { printf ("which is correct.\n\n") ;
  168. unlink (filename) ;
  169. } ;
  170. } /* show_lseek_error */
  171. static void
  172. show_stat_fstat_error (void)
  173. { static const char *filename = "stat_fstat.dat" ;
  174. static char data [256] ;
  175. int fd, mode, flags ;
  176. int stat_size, fstat_size ;
  177. struct stat buf ;
  178. /* Known to fail on WinXP. */
  179. puts ("\nstat/fstat test.\n----------------") ;
  180. printf ("0) Create a file and write %d bytes.\n", SIGNED_SIZEOF (data)) ;
  181. mode = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY ;
  182. flags = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ;
  183. if ((fd = open (filename, mode, flags)) < 0)
  184. { printf ("\n\nLine %d: open() failed : %s\n\n", __LINE__, strerror (errno)) ;
  185. return ;
  186. } ;
  187. assert (write (fd, data, sizeof (data)) > 0) ;
  188. printf ("1) Now call stat and fstat on the file and retreive the file lengths.\n") ;
  189. if (stat (filename, &buf) != 0)
  190. { printf ("\n\nLine %d: stat() failed : %s\n\n", __LINE__, strerror (errno)) ;
  191. goto error_exit ;
  192. } ;
  193. stat_size = buf.st_size ;
  194. if (fstat (fd, &buf) != 0)
  195. { printf ("\n\nLine %d: fstat() failed : %s\n\n", __LINE__, strerror (errno)) ;
  196. goto error_exit ;
  197. } ;
  198. fstat_size = buf.st_size ;
  199. printf ("2) Size returned by stat and fstat is %d and %d, ", stat_size, fstat_size) ;
  200. if (stat_size == 0 || stat_size != fstat_size)
  201. printf ("but thats just plain ***WRONG***.\n\n") ;
  202. else
  203. printf ("which is correct.\n\n") ;
  204. error_exit :
  205. close (fd) ;
  206. unlink (filename) ;
  207. return ;
  208. } /* show_stat_fstat_error */
  209. static void
  210. write_to_closed_file (void)
  211. { const char * filename = "closed_write_test.txt" ;
  212. struct stat buf ;
  213. FILE * file ;
  214. int fd ;
  215. puts ("\nWrite to closed file test.\n--------------------------") ;
  216. printf ("0) First we open file for write using fopen().\n") ;
  217. if ((file = fopen (filename, "w")) == NULL)
  218. { printf ("\n\nLine %d: fopen() failed : %s\n\n", __LINE__, strerror (errno)) ;
  219. return ;
  220. } ;
  221. printf ("1) Now we grab the file descriptor fileno().\n") ;
  222. fd = fileno (file) ;
  223. printf ("2) Write some text via the file descriptor.\n") ;
  224. assert (write (fd, "a\n", 2) > 0) ;
  225. printf ("3) Now we close the file using fclose().\n") ;
  226. fclose (file) ;
  227. stat (filename, &buf) ;
  228. printf (" File size is %d bytes.\n", (int) buf.st_size) ;
  229. printf ("4) Now write more data to the file descriptor which should fail.\n") ;
  230. if (write (fd, "b\n", 2) < 0)
  231. printf ("5) Good, write returned an error code as it should have.\n") ;
  232. else
  233. { printf ("5) Attempting to write to a closed file should have failed but didn't! *** WRONG ***\n") ;
  234. stat (filename, &buf) ;
  235. printf (" File size is %d bytes.\n", (int) buf.st_size) ;
  236. } ;
  237. unlink (filename) ;
  238. return ;
  239. } /* write_to_closed_file */