diff --git a/dlls/msvcrt/file.c b/dlls/msvcrt/file.c index a9678ed5fe9..655f17e826e 100644 --- a/dlls/msvcrt/file.c +++ b/dlls/msvcrt/file.c @@ -60,6 +60,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(msvcrt); #define WX_OPEN 0x01 #define WX_ATEOF 0x02 #define WX_READEOF 0x04 /* like ATEOF, but for underlying file rather than buffer */ +#define WX_READCR 0x08 /* underlying file is at \r */ #define WX_DONTINHERIT 0x10 #define WX_APPEND 0x20 #define WX_TEXT 0x80 @@ -941,6 +942,9 @@ int CDECL MSVCRT_fseek(MSVCRT_FILE* file, MSVCRT_long offset, int whence) if (file->_ptr[i] == '\n') offset--; } + /* Black magic when reading CR at buffer boundary*/ + if(MSVCRT_fdesc[file->_file].wxflag & WX_READCR) + offset--; } } /* Discard buffered input */ @@ -1742,6 +1746,10 @@ int CDECL _rmtmp(void) /********************************************************************* * (internal) read_i + * + * When reading \r as last character in text mode, read() positions + * the file pointer on the \r character while getc() goes on to + * the following \n */ static int read_i(int fd, void *buf, unsigned int count) { @@ -1768,6 +1776,13 @@ static int read_i(int fd, void *buf, unsigned int count) if (MSVCRT_fdesc[fd].wxflag & WX_TEXT) { DWORD i, j; + if (bufstart[num_read-1] == '\r') + { + MSVCRT_fdesc[fd].wxflag |= WX_READCR; + num_read--; + } + else + MSVCRT_fdesc[fd].wxflag &= ~WX_READCR; for (i=0, j=0; i_ptr[i] == '\n') off--; } + /* Black magic when reading CR at buffer boundary*/ + if(MSVCRT_fdesc[file->_file].wxflag & WX_READCR) + off--; + } } } @@ -2916,6 +2935,9 @@ int CDECL MSVCRT_fgetpos(MSVCRT_FILE* file, MSVCRT_fpos_t *pos) if (file->_ptr[i] == '\n') off--; } + /* Black magic when reading CR at buffer boundary*/ + if(MSVCRT_fdesc[file->_file].wxflag & WX_READCR) + off--; } } } diff --git a/dlls/msvcrt/tests/file.c b/dlls/msvcrt/tests/file.c index 042a82e943d..18247adf28f 100644 --- a/dlls/msvcrt/tests/file.c +++ b/dlls/msvcrt/tests/file.c @@ -422,6 +422,35 @@ static WCHAR* AtoW( const char* p ) return buffer; } +/* Test reading in text mode when the 512'th character read is \r*/ +static void test_readboundary(void) +{ + FILE *fp; + char buf[513], rbuf[513]; + int i, j; + for (i = 0; i < 511; i++) + { + j = (i%('~' - ' ')+ ' '); + buf[i] = j; + } + buf[511] = '\n'; + buf[512] =0; + fp = fopen("boundary.tst", "wt"); + fwrite(buf, 512,1,fp); + fclose(fp); + fp = fopen("boundary.tst", "rt"); + for(i=0; i<512; i++) + { + fseek(fp,0 , SEEK_CUR); + rbuf[i] = fgetc(fp); + } + rbuf[512] =0; + fclose(fp); + unlink("boundary.tst"); + + ok(strcmp(buf, rbuf) == 0,"CRLF on buffer boundary failure\n"); + } + static void test_fgetc( void ) { char* tempf; @@ -808,15 +837,23 @@ static void test_file_write_read( void ) tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */ _lseek(tempfd, -1, FILE_END); ret = _read(tempfd,btext,LLEN); - ok(ret == 1, "_read expected 1 got bad length: %d\n", ret); + ok(ret == 1 && *btext == '\n', "_read expected 1 got bad length: %d\n", ret); _lseek(tempfd, -2, FILE_END); ret = _read(tempfd,btext,LLEN); ok(ret == 1 && *btext == '\n', "_read expected '\\n' got bad length: %d\n", ret); _lseek(tempfd, -3, FILE_END); + ret = _read(tempfd,btext,1); + ok(ret == 1 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret); + ok(tell(tempfd) == 41, "bad position %u expecting 41\n", tell(tempfd)); + _lseek(tempfd, -3, FILE_END); ret = _read(tempfd,btext,2); ok(ret == 1 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret); ok(tell(tempfd) == 42, "bad position %u expecting 42\n", tell(tempfd)); - _close(tempfd); + _lseek(tempfd, -3, FILE_END); + ret = _read(tempfd,btext,3); + ok(ret == 2 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret); + ok(tell(tempfd) == 43, "bad position %u expecting 43\n", tell(tempfd)); + _close(tempfd); ret = unlink(tempf); ok( ret == 0 ,"Can't unlink '%s': %d\n", tempf, errno); @@ -1402,6 +1439,7 @@ START_TEST(file) test_asciimode2(); test_readmode(FALSE); /* binary mode */ test_readmode(TRUE); /* ascii mode */ + test_readboundary(); test_fgetc(); test_fputc(); test_flsbuf();