You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by tr...@locus.apache.org on 2000/06/16 18:41:34 UTC
cvs commit: apache-2.0/src/main util.c
trawick 00/06/16 09:41:30
Modified: src CHANGES
src/lib/apr/file_io/unix open.c readwrite.c
src/lib/apr/test testfile.c
src/main util.c
Log:
Turn on buffering for config file reads. This is dependent on ap_fgets()
doing the right thing.
Brian Havard implemented buffering for ap_fgets() on Win32 recently; OS/2 had
it already. This provides it for Unix.
changes to ap_read(), ap_getc(), ap_fgets() for Unix:
1) this fixes a problem in where ap_open() where a lock is created for
non-buffered files
2) this fixes problems setting rv correctly in the ap_read() buffered
path
3) since ap_read() works as expected, it is possible to make ap_getc()
and ap_fgets() even smaller
4) ap_fgets() no longer cares about '\r'
Revision Changes Path
1.155 +4 -0 apache-2.0/src/CHANGES
Index: CHANGES
===================================================================
RCS file: /home/cvs/apache-2.0/src/CHANGES,v
retrieving revision 1.154
retrieving revision 1.155
diff -u -r1.154 -r1.155
--- CHANGES 2000/06/16 15:09:34 1.154
+++ CHANGES 2000/06/16 16:40:30 1.155
@@ -1,4 +1,8 @@
Changes with Apache 2.0a5
+ *) Turn on buffering for config file reads. Part of this was to
+ repair buffered I/O support in Unix and implement buffered
+ ap_fgets() for all platforms. [Brian Havard, Jeff Trawick]
+
*) Win32: Fix problem where UTC offset was not being set correctly
in the access log. Problem reported on news group by Jerry Baker.
[Bill Stoddard]
1.55 +17 -4 apache-2.0/src/lib/apr/file_io/unix/open.c
Index: open.c
===================================================================
RCS file: /home/cvs/apache-2.0/src/lib/apr/file_io/unix/open.c,v
retrieving revision 1.54
retrieving revision 1.55
diff -u -r1.54 -r1.55
--- open.c 2000/06/15 17:39:16 1.54
+++ open.c 2000/06/16 16:40:49 1.55
@@ -82,6 +82,9 @@
ap_status_t ap_open(ap_file_t **new, const char *fname, ap_int32_t flag, ap_fileperms_t perm, ap_pool_t *cont)
{
int oflags = 0;
+#if APR_HAS_THREADS
+ ap_status_t rv;
+#endif
if ((*new) == NULL) {
(*new) = (ap_file_t *)ap_pcalloc(cont, sizeof(ap_file_t));
@@ -90,10 +93,6 @@
(*new)->cntxt = cont;
(*new)->oflags = oflags;
(*new)->filedes = -1;
- (*new)->buffer = NULL;
-#if APR_HAS_THREADS
- ap_create_lock(&((*new)->thlock), APR_MUTEX, APR_INTRAPROCESS, NULL, cont);
-#endif
if ((flag & APR_READ) && (flag & APR_WRITE)) {
oflags = O_RDWR;
@@ -111,6 +110,20 @@
(*new)->fname = ap_pstrdup(cont, fname);
(*new)->buffered = (flag & APR_BUFFERED) > 0;
+
+ if ((*new)->buffered) {
+ (*new)->buffer = ap_palloc(cont, APR_FILE_BUFSIZE);
+#if APR_HAS_THREADS
+ rv = ap_create_lock(&((*new)->thlock), APR_MUTEX, APR_INTRAPROCESS,
+ NULL, cont);
+ if (rv) {
+ return rv;
+ }
+#endif
+ }
+ else {
+ (*new)->buffer = NULL;
+ }
if (flag & APR_CREATE) {
oflags |= O_CREAT;
1.55 +34 -61 apache-2.0/src/lib/apr/file_io/unix/readwrite.c
Index: readwrite.c
===================================================================
RCS file: /home/cvs/apache-2.0/src/lib/apr/file_io/unix/readwrite.c,v
retrieving revision 1.54
retrieving revision 1.55
diff -u -r1.54 -r1.55
--- readwrite.c 2000/06/14 02:58:34 1.54
+++ readwrite.c 2000/06/16 16:40:50 1.55
@@ -98,6 +98,9 @@
}
#endif
+/* problems:
+ * 1) ungetchar not used for buffered files
+ */
ap_status_t ap_read(ap_file_t *thefile, void *buf, ap_ssize_t *nbytes)
{
ap_ssize_t rv;
@@ -130,8 +133,13 @@
thefile->dataRead = read(thefile->filedes, thefile->buffer, APR_FILE_BUFSIZE);
if (thefile->dataRead == 0) {
thefile->eof_hit = TRUE;
+ rv = APR_EOF;
break;
}
+ else if (thefile->dataRead == -1) {
+ rv = errno;
+ break;
+ }
thefile->filePtr += thefile->dataRead;
thefile->bufpos = 0;
}
@@ -143,7 +151,10 @@
size -= blocksize;
}
- *nbytes = rv == 0 ? pos - (char *)buf : 0;
+ *nbytes = pos - (char *)buf;
+ if (*nbytes) {
+ rv = 0;
+ }
#if APR_HAS_THREADS
ap_unlock(thefile->thlock);
#endif
@@ -301,22 +312,9 @@
ap_status_t ap_getc(char *ch, ap_file_t *thefile)
{
- ssize_t rv;
-
- if (thefile->ungetchar != -1) {
- *ch = (char) thefile->ungetchar;
- thefile->ungetchar = -1;
- return APR_SUCCESS;
- }
- rv = read(thefile->filedes, ch, 1);
- if (rv == 0) {
- thefile->eof_hit = TRUE;
- return APR_EOF;
- }
- else if (rv != 1) {
- return errno;
- }
- return APR_SUCCESS;
+ ap_ssize_t nbytes = 1;
+
+ return ap_read(thefile, ch, &nbytes);
}
ap_status_t ap_puts(char *str, ap_file_t *thefile)
@@ -356,59 +354,34 @@
ap_status_t ap_fgets(char *str, int len, ap_file_t *thefile)
{
- ssize_t rv;
- int i, used_unget = FALSE, beg_idx;
-
- if (len <= 1) { /* as per fgets() */
+ ap_status_t rv = APR_SUCCESS; /* get rid of gcc warning */
+ ap_ssize_t nbytes;
+ char *final = str + len - 1;
+
+ if (len <= 1) {
+ /* sort of like fgets(), which returns NULL and stores no bytes
+ */
return APR_SUCCESS;
}
- if (thefile->ungetchar != -1) {
- str[0] = thefile->ungetchar;
- used_unget = TRUE;
- beg_idx = 1;
- if (str[0] == '\n' || str[0] == '\r') {
- thefile->ungetchar = -1;
- str[1] = '\0';
- return APR_SUCCESS;
- }
- }
- else {
- beg_idx = 0;
- }
-
- for (i = beg_idx; i < len; i++) {
- rv = read(thefile->filedes, &str[i], 1);
- if (rv == 0) {
- thefile->eof_hit = TRUE;
- if (used_unget) {
- thefile->filedes = -1;
- }
- str[i] = '\0';
- return APR_EOF;
- }
- else if (rv != 1) {
- return errno;
+ while (str < final) { /* leave room for trailing '\0' */
+ nbytes = 1;
+ rv = ap_read(thefile, str, &nbytes);
+ if (rv != APR_SUCCESS) {
+ break;
}
- if (str[i] == '\n' || str[i] == '\r') {
+ if (*str == '\n') {
+ ++str;
break;
}
+ ++str;
}
- if (i < len-1) {
- str[i+1] = '\0';
- }
- return APR_SUCCESS;
-}
-
-#if 0 /* not currently used */
-static int printf_flush(ap_vformatter_buff_t *vbuff)
-{
- /* I would love to print this stuff out to the file, but I will
- * get that working later. :) For now, just return.
+ /* We must store a terminating '\0' if we've stored any chars. We can
+ * get away with storing it if we hit an error first.
*/
- return -1;
+ *str = '\0';
+ return rv;
}
-#endif
APR_EXPORT(int) ap_fprintf(ap_file_t *fptr, const char *format, ...)
{
1.14 +200 -0 apache-2.0/src/lib/apr/test/testfile.c
Index: testfile.c
===================================================================
RCS file: /home/cvs/apache-2.0/src/lib/apr/test/testfile.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- testfile.c 2000/05/24 22:32:44 1.13
+++ testfile.c 2000/06/16 16:41:09 1.14
@@ -52,6 +52,7 @@
* <http://www.apache.org/>.
*/
+#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "apr_file_io.h"
@@ -65,6 +66,7 @@
int test_filedel(ap_pool_t *);
int testdirs(ap_pool_t *);
+static void test_read(ap_pool_t *);
int main()
{
@@ -239,6 +241,7 @@
testdirs(context);
test_filedel(context);
+ test_read(context);
return 1;
}
@@ -382,4 +385,201 @@
return 1;
}
+
+#define TESTREAD_BLKSIZE 1024
+#define APR_BUFFERSIZE 4096 /* This should match APR's buffer size. */
+
+static void create_testread(ap_pool_t *p, const char *fname)
+{
+ ap_file_t *f = NULL;
+ ap_status_t rv;
+ char buf[TESTREAD_BLKSIZE];
+ ap_ssize_t nbytes;
+
+ /* Create a test file with known content.
+ */
+ rv = ap_open(&f, fname, APR_CREATE | APR_WRITE | APR_TRUNCATE, APR_UREAD | APR_UWRITE, p);
+ if (rv) {
+ fprintf(stderr, "ap_open()->%d/%s\n",
+ rv, ap_strerror(rv, buf, sizeof buf));
+ exit(1);
+ }
+ nbytes = 4;
+ rv = ap_write(f, "abc\n", &nbytes);
+ assert(!rv && nbytes == 4);
+ memset(buf, 'a', sizeof buf);
+ nbytes = sizeof buf;
+ rv = ap_write(f, buf, &nbytes);
+ assert(!rv && nbytes == sizeof buf);
+ nbytes = 2;
+ rv = ap_write(f, "\n\n", &nbytes);
+ assert(!rv && nbytes == 2);
+ rv = ap_close(f);
+ assert(!rv);
+}
+
+static char read_one(ap_file_t *f, int expected)
+{
+ char bytes[3];
+ ap_status_t rv;
+ static int counter = 0;
+ ap_ssize_t nbytes;
+
+ counter += 1;
+
+ bytes[0] = bytes[2] = 0x01;
+ if (counter % 2) {
+ rv = ap_getc(bytes + 1, f);
+ }
+ else {
+ nbytes = 1;
+ rv = ap_read(f, bytes + 1, &nbytes);
+ assert(nbytes == 1);
+ }
+ assert(!rv);
+ assert(bytes[0] == 0x01 && bytes[2] == 0x01);
+ if (expected != -1) {
+ assert(bytes[1] == expected);
+ }
+ return bytes[1];
+}
+
+static void test_read_guts(ap_pool_t *p, const char *fname, ap_int32_t extra_flags)
+{
+ ap_file_t *f = NULL;
+ ap_status_t rv;
+ ap_ssize_t nbytes;
+ char buf[1024];
+ int i;
+
+ rv = ap_open(&f, fname, APR_READ | extra_flags, 0, p);
+ assert(!rv);
+ read_one(f, 'a');
+ read_one(f, 'b');
+ if (extra_flags & APR_BUFFERED) {
+ fprintf(stdout,
+ "\n\t\tskipping ap_ungetc() for APR_BUFFERED... "
+ "doesn't work yet...\n\t\t\t\t ");
+ }
+ else {
+ rv = ap_ungetc('z', f);
+ assert(!rv);
+ rv = ap_ungetc('a', f);
+ assert(!rv); /* we just overwrote the previously-un-got char */
+ read_one(f, 'a');
+ }
+ read_one(f, 'c');
+ read_one(f, '\n');
+ for (i = 0; i < TESTREAD_BLKSIZE; i++) {
+ read_one(f, 'a');
+ }
+ read_one(f, '\n');
+ read_one(f, '\n');
+ rv = ap_getc(buf, f);
+ assert(rv == APR_EOF);
+ rv = ap_close(f);
+ assert(!rv);
+
+ f = NULL;
+ rv = ap_open(&f, fname, APR_READ | extra_flags, 0, p);
+ assert(!rv);
+ rv = ap_fgets(buf, 10, f);
+ assert(!rv);
+ assert(!strcmp(buf, "abc\n"));
+ /* read first 800 of TESTREAD_BLKSIZE 'a's
+ */
+ rv = ap_fgets(buf, 801, f);
+ assert(!rv);
+ assert(strlen(buf) == 800);
+ for (i = 0; i < 800; i++) {
+ assert(buf[i] == 'a');
+ }
+ /* read rest of the 'a's and the first newline
+ */
+ rv = ap_fgets(buf, sizeof buf, f);
+ assert(!rv);
+ assert(strlen(buf) == TESTREAD_BLKSIZE - 800 + 1);
+ for (i = 0; i < TESTREAD_BLKSIZE - 800; i++) {
+ assert(buf[i] == 'a');
+ }
+ assert(buf[TESTREAD_BLKSIZE - 800] == '\n');
+ /* read the last newline
+ */
+ rv = ap_fgets(buf, sizeof buf, f);
+ assert(!rv);
+ assert(!strcmp(buf, "\n"));
+ /* get APR_EOF
+ */
+ rv = ap_fgets(buf, sizeof buf, f);
+ assert(rv == APR_EOF);
+ /* get APR_EOF with ap_getc
+ */
+ rv = ap_getc(buf, f);
+ assert(rv == APR_EOF);
+ /* get APR_EOF with ap_read
+ */
+ nbytes = sizeof buf;
+ rv = ap_read(f, buf, &nbytes);
+ assert(rv == APR_EOF);
+ rv = ap_close(f);
+ assert(!rv);
+}
+
+static void test_bigread(ap_pool_t *p, const char *fname, ap_int32_t extra_flags)
+{
+ ap_file_t *f = NULL;
+ ap_status_t rv;
+ char buf[APR_BUFFERSIZE * 2];
+ ap_ssize_t nbytes;
+
+ /* Create a test file with known content.
+ */
+ rv = ap_open(&f, fname, APR_CREATE | APR_WRITE | APR_TRUNCATE, APR_UREAD | APR_UWRITE, p);
+ if (rv) {
+ fprintf(stderr, "ap_open()->%d/%s\n",
+ rv, ap_strerror(rv, buf, sizeof buf));
+ exit(1);
+ }
+ nbytes = APR_BUFFERSIZE;
+ memset(buf, 0xFE, nbytes);
+ rv = ap_write(f, buf, &nbytes);
+ assert(!rv && nbytes == APR_BUFFERSIZE);
+ rv = ap_close(f);
+ assert(!rv);
+
+ f = NULL;
+ rv = ap_open(&f, fname, APR_READ | extra_flags, 0, p);
+ assert(!rv);
+ nbytes = sizeof buf;
+ rv = ap_read(f, buf, &nbytes);
+ assert(!rv);
+ assert(nbytes == APR_BUFFERSIZE);
+ rv = ap_close(f);
+ assert(!rv);
+}
+
+static void test_read(ap_pool_t *p)
+{
+ const char *fname = "testread.dat";
+ ap_status_t rv;
+
+ fprintf(stdout, "Testing file read functions.\n");
+
+ create_testread(p, fname);
+ fprintf(stdout, "\tBuffered file tests......");
+ test_read_guts(p, fname, APR_BUFFERED);
+ fprintf(stdout, "OK\n");
+ fprintf(stdout, "\tUnbuffered file tests....");
+ test_read_guts(p, fname, 0);
+ fprintf(stdout, "OK\n");
+ fprintf(stdout, "\tMore buffered file tests......");
+ test_bigread(p, fname, APR_BUFFERED);
+ fprintf(stdout, "OK\n");
+ fprintf(stdout, "\tMore unbuffered file tests......");
+ test_bigread(p, fname, 0);
+ fprintf(stdout, "OK\n");
+ rv = ap_remove_file(fname, p);
+ assert(!rv);
+ fprintf(stdout, "\tAll read tests...........OK\n");
+}
1.54 +1 -1 apache-2.0/src/main/util.c
Index: util.c
===================================================================
RCS file: /home/cvs/apache-2.0/src/main/util.c,v
retrieving revision 1.53
retrieving revision 1.54
diff -u -r1.53 -r1.54
--- util.c 2000/06/13 21:36:17 1.53
+++ util.c 2000/06/16 16:41:21 1.54
@@ -874,7 +874,7 @@
return APR_EACCES;
}
- status = ap_open(&file, name, APR_READ, APR_OS_DEFAULT, p);
+ status = ap_open(&file, name, APR_READ | APR_BUFFERED, APR_OS_DEFAULT, p);
#ifdef DEBUG
ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, NULL,
"Opening config file %s (%s)",