fclose.c 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. /* Copyright (C) 2004 Manuel Novoa III <mjn3@codepoet.org>
  2. *
  3. * GNU Library General Public License (LGPL) version 2 or later.
  4. *
  5. * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details.
  6. */
  7. #include "_stdio.h"
  8. int fclose(register FILE *stream)
  9. {
  10. int rv = 0;
  11. __STDIO_AUTO_THREADLOCK_VAR;
  12. #ifdef __STDIO_HAS_OPENLIST
  13. #if !defined(__UCLIBC_HAS_THREADS__) || !defined(__STDIO_BUFFERS)
  14. /* First, remove the file from the open file list. */
  15. {
  16. FILE *ptr;
  17. __STDIO_THREADLOCK_OPENLIST_DEL;
  18. __STDIO_THREADLOCK_OPENLIST_ADD;
  19. ptr = _stdio_openlist;
  20. if ((ptr = _stdio_openlist) == stream) {
  21. _stdio_openlist = stream->__nextopen;
  22. } else {
  23. while (ptr) {
  24. if (ptr->__nextopen == stream) {
  25. ptr->__nextopen = stream->__nextopen;
  26. break;
  27. }
  28. ptr = ptr->__nextopen;
  29. }
  30. }
  31. __STDIO_THREADUNLOCK_OPENLIST_ADD;
  32. __STDIO_THREADUNLOCK_OPENLIST_DEL;
  33. }
  34. #endif
  35. #endif
  36. __STDIO_AUTO_THREADLOCK(stream);
  37. __STDIO_STREAM_VALIDATE(stream);
  38. #ifdef __STDIO_BUFFERS
  39. /* Write any pending buffered chars. */
  40. if (__STDIO_STREAM_IS_WRITING(stream)) {
  41. rv = fflush_unlocked(stream);
  42. }
  43. #endif
  44. if (__CLOSE(stream) < 0) { /* Must close even if fflush failed. */
  45. rv = EOF;
  46. }
  47. stream->__filedes = -1;
  48. /* We need a way for freopen to know that a file has been closed.
  49. * Since a file can't be both readonly and writeonly, that makes
  50. * an effective signal. It also has the benefit of disabling
  51. * transitions to either reading or writing. */
  52. #if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS)
  53. /* Before we mark the file as closed, make sure we increment the openlist use count
  54. * so it isn't freed under us while still cleaning up. */
  55. __STDIO_OPENLIST_INC_USE;
  56. #endif
  57. stream->__modeflags &= (__FLAG_FREEBUF|__FLAG_FREEFILE);
  58. stream->__modeflags |= (__FLAG_READONLY|__FLAG_WRITEONLY);
  59. #ifndef NDEBUG
  60. /* Reinitialize everything (including putc since fflush could fail). */
  61. __STDIO_STREAM_DISABLE_GETC(stream);
  62. __STDIO_STREAM_DISABLE_PUTC(stream);
  63. __STDIO_STREAM_INIT_BUFREAD_BUFPOS(stream);
  64. # ifdef __UCLIBC_HAS_WCHAR__
  65. stream->__ungot_width[0] = 0;
  66. # endif
  67. # ifdef __STDIO_MBSTATE
  68. __INIT_MBSTATE(&(stream->__state));
  69. # endif
  70. #endif
  71. __STDIO_AUTO_THREADUNLOCK(stream);
  72. __STDIO_STREAM_FREE_BUFFER(stream);
  73. #if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS)
  74. /* inefficient - locks/unlocks twice and walks whole list */
  75. __STDIO_OPENLIST_INC_DEL_CNT;
  76. __STDIO_OPENLIST_DEC_USE; /* This with free the file if necessary. */
  77. #else
  78. __STDIO_STREAM_FREE_FILE(stream);
  79. #endif
  80. return rv;
  81. }
  82. libc_hidden_def(fclose)