fclose.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  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. libc_hidden_proto(fclose)
  9. libc_hidden_proto(close)
  10. libc_hidden_proto(fflush_unlocked)
  11. int fclose(register FILE *stream)
  12. {
  13. int rv = 0;
  14. __STDIO_AUTO_THREADLOCK_VAR;
  15. #ifdef __UCLIBC_MJN3_ONLY__
  16. #warning REMINDER: dead code... but may want to simply check and not remove
  17. #endif
  18. /* #ifdef __STDIO_HAS_OPENLIST */
  19. /* #if !defined(__UCLIBC_HAS_THREADS__) || !defined(__STDIO_BUFFERS) */
  20. /* /\* First, remove the file from the open file list. *\/ */
  21. /* { */
  22. /* register FILE *ptr; */
  23. /* __STDIO_THREADLOCK_OPENLIST; */
  24. /* if ((ptr = _stdio_openlist) == stream) { */
  25. /* #warning does a mod!!! */
  26. /* _stdio_openlist = stream->__nextopen; */
  27. /* } else { */
  28. /* while (ptr) { */
  29. /* if (ptr->__nextopen == stream) { */
  30. /* ptr->__nextopen = stream->__nextopen; */
  31. /* break; */
  32. /* } */
  33. /* ptr = ptr->__nextopen; */
  34. /* } */
  35. /* } */
  36. /* __STDIO_THREADUNLOCK_OPENLIST; */
  37. /* if (!ptr) { /\* Did not find stream in the open file list! *\/ */
  38. /* return EOF; */
  39. /* } */
  40. /* } */
  41. /* #endif */
  42. /* #endif */
  43. __STDIO_AUTO_THREADLOCK(stream);
  44. __STDIO_STREAM_VALIDATE(stream);
  45. #ifdef __STDIO_BUFFERS
  46. /* Write any pending buffered chars. */
  47. if (__STDIO_STREAM_IS_WRITING(stream)) {
  48. rv = fflush_unlocked(stream);
  49. }
  50. #endif
  51. if (__CLOSE(stream) < 0) { /* Must close even if fflush failed. */
  52. rv = EOF;
  53. }
  54. stream->__filedes = -1;
  55. /* We need a way for freopen to know that a file has been closed.
  56. * Since a file can't be both readonly and writeonly, that makes
  57. * an effective signal. It also has the benefit of disabling
  58. * transitions to either reading or writing. */
  59. #if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS)
  60. /* Before we mark the file as closed, make sure we increment the openlist use count
  61. * so it isn't freed under us while still cleaning up. */
  62. __STDIO_OPENLIST_INC_USE;
  63. #endif
  64. stream->__modeflags &= (__FLAG_FREEBUF|__FLAG_FREEFILE);
  65. stream->__modeflags |= (__FLAG_READONLY|__FLAG_WRITEONLY);
  66. #ifndef NDEBUG
  67. __STDIO_STREAM_RESET_GCS(stream);
  68. /* Reinitialize everything (including putc since fflush could fail). */
  69. __STDIO_STREAM_DISABLE_GETC(stream);
  70. __STDIO_STREAM_DISABLE_PUTC(stream);
  71. __STDIO_STREAM_INIT_BUFREAD_BUFPOS(stream);
  72. # ifdef __UCLIBC_HAS_WCHAR__
  73. stream->__ungot_width[0] = 0;
  74. # endif
  75. # ifdef __STDIO_MBSTATE
  76. __INIT_MBSTATE(&(stream->__state));
  77. # endif
  78. #endif
  79. __STDIO_AUTO_THREADUNLOCK(stream);
  80. __STDIO_STREAM_FREE_BUFFER(stream);
  81. #ifdef __UCLIBC_MJN3_ONLY__
  82. #warning REMINDER: inefficient - locks and unlocks twice and walks whole list
  83. #endif
  84. #if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS)
  85. /* inefficient - locks/unlocks twice and walks whole list */
  86. __STDIO_OPENLIST_INC_DEL_CNT;
  87. __STDIO_OPENLIST_DEC_USE; /* This with free the file if necessary. */
  88. #else
  89. __STDIO_STREAM_FREE_FILE(stream);
  90. #endif
  91. return rv;
  92. }
  93. libc_hidden_def(fclose)