Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:10339 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 93794 invoked by uid 1010); 9 Jun 2004 09:41:23 -0000 Delivered-To: ezmlm-scan-internals@lists.php.net Delivered-To: ezmlm-internals@lists.php.net Received: (qmail 93728 invoked by uid 1007); 9 Jun 2004 09:41:22 -0000 To: internals@lists.php.net References: <5.1.0.14.2.20040607170659.01f2fc08@127.0.0.1> <20040607200254.2f3fab48.tony2001@phpclub.net> <1086691893.2138.3.camel@mopo.tv2i.dk> Message-ID: Date: Wed, 09 Jun 2004 12:40:56 +0300 Organization: none Content-Type: text/plain; format=flowed; delsp=yes; charset=koi8-r MIME-Version: 1.0 Content-Transfer-Encoding: 8bit User-Agent: Opera M2/7.50 (Win32, build 3778) X-Posted-By: 217.23.116.150 Subject: Re: [PHP-DEV] readfile() improvements From: valyala@tut.by ("Alexander Valyalkin") On Tue, 08 Jun 2004 12:51:33 +0200, Morten K. Poulsen wrote: > On Tue, 2004-06-08 at 11:32, Alexander Valyalkin wrote: >> + /* get the length of local file connected to descriptor fd */ >> fstat(fd, &sbuf); > [snip] >> + if (errno) { > > Oh-oh! You need to check the return value of fstat(). Errno is only set > if fstat() fails (returns -1), otherwise errno keeps its old (junk) > value. > > Best regards, > Morten > Thanks for useful remark. Here is corrected code & unified diff: =====================cut=================== PHPAPI size_t _php_stream_passthru(php_stream * stream STREAMS_DC TSRMLS_DC) { size_t bcount = 0; /* counter of printed out bytes */ int is_mapped = 0; char buf[8192]; size_t buf_len = sizeof(buf); #ifdef HAVE_MMAP int fd; if (!php_stream_is(stream, PHP_STREAM_IS_SOCKET) && stream->filterhead == NULL && php_stream_tell(stream) == 0 && SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD, (void*)&fd, 0)) { is_mapped = 1; buf_len = 1024 * 1024; /* default length of the mapped memory */ struct stat sbuf; void *p; /* pinter to the mapped part of file */ size_t len; /* get the length of local file connected to descriptor fd */ if (fstat(fd, &sbuf)) { /* cannot get length of file */ php_error_docref(NULL TSRMLS_CC, E_ERROR, "cannot get length of the file"); return bcount; } len = (size_t) sbuf.st_size; /* print to the output buffer file contents */ while (bcount < len) { if (len - bcount < buf_len) buf_len = len - bcount; p = mmap(NULL, buf_len, PROT_READ, MAP_SHARED, fd, (off_t) bcount); /* try to map part of the file to memory */ if (p == (void *) MAP_FAILED) { /* error when mapping part of the file to memory */ php_error_docref(NULL TSRMLS_CC, E_ERROR, "mmap error: cannot map part of the file to memory"); break; } PHPWRITE(p, buf_len); if (munmap(p, buf_len)) { /* error when unmapping memory */ php_error_docref(NULL TSRMLS_CC, E_ERROR, "mmap error: cannot unmap allocated memory"); break; } bcount += buf_len; } } #endif if (!is_mapped) { /* print to the output buffer stream contents */ while ((buf_len = php_stream_read(stream, buf, sizeof(buf))) > 0) { PHPWRITE(buf, buf_len); bcount += buf_len; } } return bcount; } =====================cut=================== unfified diff =====================cut=================== --- streams.c Wed May 12 13:46:30 2004 +++ streams_new.c Wed Jun 09 12:37:31 2004 @@ -1062,48 +1062,54 @@ PHPAPI size_t _php_stream_passthru(php_stream * stream STREAMS_DC TSRMLS_DC) { - size_t bcount = 0; - int ready = 0; + size_t bcount = 0; /* counter of printed out bytes */ + int is_mapped = 0; char buf[8192]; + size_t buf_len = sizeof(buf); #ifdef HAVE_MMAP int fd; -#endif -#ifdef HAVE_MMAP if (!php_stream_is(stream, PHP_STREAM_IS_SOCKET) && stream->filterhead == NULL && php_stream_tell(stream) == 0 && SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD, (void*)&fd, 0)) { + is_mapped = 1; + buf_len = 1024 * 1024; /* default length of the mapped memory */ struct stat sbuf; - off_t off; - void *p; + void *p; /* pinter to the mapped part of file */ size_t len; - - fstat(fd, &sbuf); - - if (sbuf.st_size > sizeof(buf)) { - off = php_stream_tell(stream); - len = sbuf.st_size - off; - p = mmap(0, len, PROT_READ, MAP_SHARED, fd, off); - if (p != (void *) MAP_FAILED) { - BG(mmap_file) = p; - BG(mmap_len) = len; - PHPWRITE(p, len); - BG(mmap_file) = NULL; - munmap(p, len); - bcount += len; - ready = 1; + /* get the length of local file connected to descriptor fd */ + if (fstat(fd, &sbuf)) { + /* cannot get length of file */ + php_error_docref(NULL TSRMLS_CC, E_ERROR, "cannot get length of the file"); + return bcount; + } + len = (size_t) sbuf.st_size; + /* print to the output buffer file contents */ + while (bcount < len) { + if (len - bcount < buf_len) buf_len = len - bcount; + p = mmap(NULL, buf_len, PROT_READ, MAP_SHARED, fd, (off_t) bcount); /* try to map part of the file to memory */ + if (p == (void *) MAP_FAILED) { + /* error when mapping part of the file to memory */ + php_error_docref(NULL TSRMLS_CC, E_ERROR, "mmap error: cannot map part of the file to memory"); + break; + } + PHPWRITE(p, buf_len); + if (munmap(p, buf_len)) { + /* error when unmapping memory */ + php_error_docref(NULL TSRMLS_CC, E_ERROR, "mmap error: cannot unmap allocated memory"); + break; } + bcount += buf_len; } } #endif - if(!ready) { - int b; - - while ((b = php_stream_read(stream, buf, sizeof(buf))) > 0) { - PHPWRITE(buf, b); - bcount += b; + if (!is_mapped) { + /* print to the output buffer stream contents */ + while ((buf_len = php_stream_read(stream, buf, sizeof(buf))) > 0) { + PHPWRITE(buf, buf_len); + bcount += buf_len; } } return bcount; =====================cut=================== -- Using Opera's revolutionary e-mail client: http://www.opera.com/m2/