freopen.c 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  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. #ifdef __DO_LARGEFILE
  9. # ifndef __UCLIBC_HAS_LFS__
  10. # error large file support is not enabled!
  11. # endif
  12. # define freopen freopen64
  13. # define FILEDES_ARG (-2)
  14. #else
  15. # define FILEDES_ARG (-1)
  16. #endif
  17. FILE *freopen(const char * __restrict filename, const char * __restrict mode,
  18. register FILE * __restrict stream)
  19. {
  20. /*
  21. * ANSI/ISO allow (implementation-defined) change of mode for an
  22. * existing file if filename is NULL. It doesn't look like Linux
  23. * supports this, so we don't here.
  24. *
  25. * NOTE: Whether or not the stream is free'd on failure is unclear
  26. * w.r.t. ANSI/ISO. This implementation chooses to NOT free
  27. * the stream and associated buffer if they were dynamically
  28. * allocated.
  29. * NOTE: Previous versions of uClibc did free dynamic storage.
  30. *
  31. * TODO: Apparently linux allows setting append mode. Implement?
  32. */
  33. unsigned short dynmode;
  34. register FILE *fp;
  35. __STDIO_AUTO_THREADLOCK_VAR;
  36. __STDIO_AUTO_THREADLOCK(stream);
  37. __STDIO_STREAM_VALIDATE(stream);
  38. /* First, flush and close, but don't deallocate, the stream. */
  39. /* This also removes the stream for the open file list. */
  40. dynmode = (stream->__modeflags & (__FLAG_FREEBUF|__FLAG_FREEFILE));
  41. stream->__modeflags &= ~(__FLAG_FREEBUF|__FLAG_FREEFILE);
  42. /* Only call fclose on the stream if it is not already closed. */
  43. if ((stream->__modeflags & (__FLAG_READONLY|__FLAG_WRITEONLY))
  44. != (__FLAG_READONLY|__FLAG_WRITEONLY)
  45. ) {
  46. fclose(stream); /* Failures are ignored. */
  47. }
  48. fp = _stdio_fopen(((intptr_t) filename), mode, stream, FILEDES_ARG);
  49. /* Reset the allocation flags. */
  50. stream->__modeflags |= dynmode;
  51. __STDIO_AUTO_THREADUNLOCK(stream);
  52. return fp;
  53. }