freopen.c 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  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. #ifndef __DO_LARGEFILE
  10. # define FILEDES_ARG (-1)
  11. #endif
  12. FILE *freopen(const char * __restrict filename, const char * __restrict mode,
  13. register FILE * __restrict stream)
  14. {
  15. /*
  16. * ANSI/ISO allow (implementation-defined) change of mode for an
  17. * existing file if filename is NULL. It doesn't look like Linux
  18. * supports this, so we don't here.
  19. *
  20. * NOTE: Whether or not the stream is free'd on failure is unclear
  21. * w.r.t. ANSI/ISO. This implementation chooses to NOT free
  22. * the stream and associated buffer if they were dynamically
  23. * allocated.
  24. * NOTE: Previous versions of uClibc did free dynamic storage.
  25. *
  26. * TODO: Apparently linux allows setting append mode. Implement?
  27. */
  28. unsigned short dynmode;
  29. register FILE *fp;
  30. __STDIO_AUTO_THREADLOCK_VAR;
  31. __STDIO_AUTO_THREADLOCK(stream);
  32. __STDIO_STREAM_VALIDATE(stream);
  33. __STDIO_OPENLIST_INC_USE; /* Do not remove the file from the list. */
  34. /* First, flush and close, but don't deallocate, the stream. */
  35. /* This also removes the stream for the open file list. */
  36. dynmode = (stream->__modeflags & (__FLAG_FREEBUF|__FLAG_FREEFILE));
  37. stream->__modeflags &= ~(__FLAG_FREEBUF|__FLAG_FREEFILE);
  38. /* Only call fclose on the stream if it is not already closed. */
  39. if ((stream->__modeflags & (__FLAG_READONLY|__FLAG_WRITEONLY))
  40. != (__FLAG_READONLY|__FLAG_WRITEONLY)
  41. ) {
  42. fclose(stream); /* Failures are ignored. */
  43. /* NOTE: fclose always does __STDIO_OPENLIST_INC_DEL_CNT. But we don't
  44. * want to remove this FILE from the open list, even if the freopen fails.
  45. * Consider the case of a failed freopen() on stdin. You probably still
  46. * want to be able to call freopen() again. Similarly for other "malloc'd"
  47. * streams. */
  48. __STDIO_OPENLIST_DEC_DEL_CNT;
  49. }
  50. fp = _stdio_fopen(((intptr_t) filename), mode, stream, FILEDES_ARG);
  51. if (!fp) {
  52. /* Don't remove stream from the open file list and (potentially) free it.
  53. * See _stdio_openlist_dec_use() in fflush.c. */
  54. stream->__modeflags = __FLAG_READONLY|__FLAG_WRITEONLY|__FLAG_FAILED_FREOPEN;
  55. }
  56. /* Reset the allocation flags. */
  57. stream->__modeflags |= dynmode;
  58. __STDIO_OPENLIST_DEC_USE;
  59. __STDIO_AUTO_THREADUNLOCK(stream);
  60. return fp;
  61. }