Re: readfile() improvements

From: Date: Wed, 09 Jun 2004 09:40:56 +0000
Subject: Re: readfile() improvements
References: 1 2 3 4 5 6  Groups: php.internals 
Request: Send a blank email to internals+get-10339@lists.php.net to get a copy of this message
On Tue, 08 Jun 2004 12:51:33 +0200, Morten K. Poulsen <morten-VxKok5x5@afdelingp.dk> 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/

« previous php.internals (#10339) next »