1 // 2 // rewind.cpp 3 // 4 // Copyright (c) Microsoft Corporation. All rights reserved. 5 // 6 // Defines rewind(), which rewinds a stream. 7 // 8 #include <corecrt_internal_stdio.h> 9 #include <corecrt_internal_ptd_propagation.h> 10 11 12 13 // Rewinds a stream back to the beginning, if the stream supports seeking. The 14 // stream is flushed and errors are cleared before the rewind. 15 static void __cdecl _rewind_internal(FILE* const public_stream, __crt_cached_ptd_host& ptd) 16 { 17 __crt_stdio_stream const stream(public_stream); 18 19 _UCRT_VALIDATE_RETURN_VOID(ptd, stream.valid(), EINVAL); 20 21 int const fh = _fileno(stream.public_stream()); 22 23 _lock_file(stream.public_stream()); 24 __try 25 { 26 // Flush the streeam, reset the error state, and seek back to the 27 // beginning: 28 __acrt_stdio_flush_nolock(stream.public_stream(), ptd); 29 // If the stream is opened in update mode and is currently in use for reading, 30 // the buffer must be abandoned to ensure consistency when transitioning from 31 // reading to writing. 32 // __acrt_stdio_flush_nolock will not reset the buffer when _IOWRITE flag 33 // is not set. 34 __acrt_stdio_reset_buffer(stream); 35 36 37 stream.unset_flags(_IOERROR | _IOEOF); 38 _osfile_safe(fh) &= ~(FEOFLAG); 39 40 if (stream.has_all_of(_IOUPDATE)) 41 { 42 stream.unset_flags(_IOREAD | _IOWRITE); 43 } 44 45 if (_lseek_internal(fh, 0, 0, ptd) == -1) 46 { 47 stream.set_flags(_IOERROR); 48 } 49 } 50 __finally 51 { 52 _unlock_file(stream.public_stream()); 53 } 54 __endtry 55 } 56 57 extern "C" void __cdecl rewind(FILE* const public_stream) 58 { 59 __crt_cached_ptd_host ptd; 60 _rewind_internal(public_stream, ptd); 61 } 62