diff options
author | Pierre-Yves Ritschard <pyr@cvs.openbsd.org> | 2009-06-02 23:36:41 +0000 |
---|---|---|
committer | Pierre-Yves Ritschard <pyr@cvs.openbsd.org> | 2009-06-02 23:36:41 +0000 |
commit | a3e8d50e99168183daf1fcbb0d28c78a9afb45bd (patch) | |
tree | 30345c013a8fe61f538e80291d51600d9410cac1 | |
parent | c64ba8f3144a9836b3320d154687ecf20b07135c (diff) |
Fix the way apache reports Content-Length by promoting the clength field
of request_rec from long to off_t, which makes it 64bit on i386.
This allows files bigger than 2gig to be correctly served on arches
where long is only 32bits.
Warning: this introduces an ABI break, and hence some third party
apache modules will need to be rebuilt to correctly link to this new
apache.
ok miod@, deraadt@
-rw-r--r-- | usr.sbin/httpd/src/include/http_protocol.h | 6 | ||||
-rw-r--r-- | usr.sbin/httpd/src/include/httpd.h | 4 | ||||
-rw-r--r-- | usr.sbin/httpd/src/main/http_protocol.c | 47 |
3 files changed, 31 insertions, 26 deletions
diff --git a/usr.sbin/httpd/src/include/http_protocol.h b/usr.sbin/httpd/src/include/http_protocol.h index 7afa88a497e..39e416e7e2a 100644 --- a/usr.sbin/httpd/src/include/http_protocol.h +++ b/usr.sbin/httpd/src/include/http_protocol.h @@ -1,4 +1,4 @@ -/* $OpenBSD: http_protocol.h,v 1.11 2005/03/28 23:26:51 niallo Exp $ */ +/* $OpenBSD: http_protocol.h,v 1.12 2009/06/02 23:36:40 pyr Exp $ */ /* ==================================================================== * The Apache Software License, Version 1.1 @@ -115,7 +115,7 @@ API_EXPORT(void) ap_send_error_response(request_rec *r, int recursive_error); * permit_cache argument is set to one). */ -API_EXPORT(int) ap_set_content_length(request_rec *r, long length); +API_EXPORT(int) ap_set_content_length(request_rec *r, off_t length); API_EXPORT(int) ap_set_keepalive(request_rec *r); API_EXPORT(time_t) ap_rationalize_mtime(request_rec *r, time_t mtime); API_EXPORT(char *) ap_make_etag(request_rec *r, int force_weak); @@ -173,7 +173,7 @@ API_EXPORT(int) ap_discard_request_body(request_rec *r); /* Sending a byterange */ API_EXPORT(int) ap_set_byterange(request_rec *r); -API_EXPORT(int) ap_each_byterange(request_rec *r, long *offset, long *length); +API_EXPORT(int) ap_each_byterange(request_rec *r, off_t *offset, off_t *length); /* Support for the Basic authentication protocol. Note that there's * nothing that prevents these from being in mod_auth.c, except that other diff --git a/usr.sbin/httpd/src/include/httpd.h b/usr.sbin/httpd/src/include/httpd.h index 957d1995cf5..bfcdc5d1038 100644 --- a/usr.sbin/httpd/src/include/httpd.h +++ b/usr.sbin/httpd/src/include/httpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: httpd.h,v 1.28 2008/05/09 08:06:28 mbalmer Exp $ */ +/* $OpenBSD: httpd.h,v 1.29 2009/06/02 23:36:40 pyr Exp $ */ /* ==================================================================== * The Apache Software License, Version 1.1 @@ -744,7 +744,7 @@ struct request_rec { int byterange; /* number of byte ranges */ char *boundary; /* multipart/byteranges boundary */ const char *range; /* The Range: header */ - long clength; /* The "real" content length */ + off_t clength; /* The "real" content length */ long remaining; /* bytes left to read */ long read_length; /* bytes that have been read */ diff --git a/usr.sbin/httpd/src/main/http_protocol.c b/usr.sbin/httpd/src/main/http_protocol.c index 5e6509631dc..c4bc80386e9 100644 --- a/usr.sbin/httpd/src/main/http_protocol.c +++ b/usr.sbin/httpd/src/main/http_protocol.c @@ -1,4 +1,4 @@ -/* $OpenBSD: http_protocol.c,v 1.34 2008/05/23 08:41:48 mbalmer Exp $ */ +/* $OpenBSD: http_protocol.c,v 1.35 2009/06/02 23:36:40 pyr Exp $ */ /* ==================================================================== * The Apache Software License, Version 1.1 @@ -139,8 +139,9 @@ enum byterange_token { }; static enum byterange_token - parse_byterange(request_rec *r, long *start, long *end) + parse_byterange(request_rec *r, off_t *start, off_t *end) { + const char *estr; /* parsing first, semantics later */ while (ap_isspace(*r->range)) @@ -155,10 +156,12 @@ static enum byterange_token return BYTERANGE_EMPTY; } - if (ap_isdigit(*r->range)) - *start = ap_strtol(r->range, (char **)&r->range, 10); - else - *start = -1; + if (ap_isdigit(*r->range)) { + *start = strtonum(r->range, QUAD_MIN, QUAD_MAX, &estr); + if (estr) + return BYTERANGE_BADSYNTAX; + } else + *start = -1; while (ap_isspace(*r->range)) ++r->range; @@ -170,10 +173,12 @@ static enum byterange_token while (ap_isspace(*r->range)) ++r->range; - if (ap_isdigit(*r->range)) - *end = ap_strtol(r->range, (char **)&r->range, 10); - else - *end = -1; + if (ap_isdigit(*r->range)) { + *end = strtonum(r->range, QUAD_MIN, QUAD_MAX, &estr); + if (estr) + return BYTERANGE_BADSYNTAX; + } else + *end = -1; while (ap_isspace(*r->range)) ++r->range; @@ -219,7 +224,7 @@ static enum byterange_token * output. If start or end are less than 0 then it will do a byterange * chunk trailer instead of a header. */ -static int byterange_boundary(request_rec *r, long start, long end, int output) +static int byterange_boundary(request_rec *r, off_t start , off_t end, int output) { int length = 0; @@ -233,7 +238,7 @@ static int byterange_boundary(request_rec *r, long start, long end, int output) const char *ct = make_content_type(r, r->content_type); char ts[MAX_STRING_LEN]; - ap_snprintf(ts, sizeof(ts), "%ld-%ld/%ld", start, end, r->clength); + ap_snprintf(ts, sizeof(ts), "%qd-%qd/%qd", start, end, r->clength); if (output) ap_rvputs(r, CRLF "--", r->boundary, CRLF "Content-type: ", ct, CRLF "Content-range: bytes ", ts, CRLF CRLF, @@ -251,7 +256,7 @@ API_EXPORT(int) ap_set_byterange(request_rec *r) const char *range, *if_range, *match; char *bbuf, *b; u_int32_t rbuf[12]; /* 48 bytes yields 64 base64 chars */ - long length, start, end, one_start = 0, one_end = 0; + off_t length, start, end, one_start = 0, one_end = 0; size_t u; int ranges, empty; @@ -348,7 +353,7 @@ API_EXPORT(int) ap_set_byterange(request_rec *r) } else { ap_table_setn(r->headers_out, "Content-Range", - ap_psprintf(r->pool, "bytes */%ld", r->clength)); + ap_psprintf(r->pool, "bytes */%qd", r->clength)); ap_set_content_length(r, 0); r->boundary = NULL; r->range = range; @@ -360,10 +365,10 @@ API_EXPORT(int) ap_set_byterange(request_rec *r) else if (ranges == 1) { /* simple handling of a single range -- no boundaries */ ap_table_setn(r->headers_out, "Content-Range", - ap_psprintf(r->pool, "bytes %ld-%ld/%ld", + ap_psprintf(r->pool, "bytes %qd-%qd/%qd", one_start, one_end, r->clength)); ap_table_setn(r->headers_out, "Content-Length", - ap_psprintf(r->pool, "%ld", one_end - one_start + 1)); + ap_psprintf(r->pool, "%qd", one_end - one_start + 1LL)); r->boundary = NULL; r->byterange = 1; r->range = range; @@ -374,7 +379,7 @@ API_EXPORT(int) ap_set_byterange(request_rec *r) /* multiple ranges */ length += byterange_boundary(r, -1, -1, 0); ap_table_setn(r->headers_out, "Content-Length", - ap_psprintf(r->pool, "%ld", length)); + ap_psprintf(r->pool, "%qd", length)); r->byterange = 2; r->range = range; r->status = PARTIAL_CONTENT; @@ -382,9 +387,9 @@ API_EXPORT(int) ap_set_byterange(request_rec *r) } } -API_EXPORT(int) ap_each_byterange(request_rec *r, long *offset, long *length) +API_EXPORT(int) ap_each_byterange(request_rec *r, off_t *offset, off_t *length) { - long start, end; + off_t start, end; do { if (parse_byterange(r, &start, &end) == BYTERANGE_OK) { @@ -400,10 +405,10 @@ API_EXPORT(int) ap_each_byterange(request_rec *r, long *offset, long *length) return 0; } -API_EXPORT(int) ap_set_content_length(request_rec *r, long clength) +API_EXPORT(int) ap_set_content_length(request_rec *r, off_t clength) { r->clength = clength; - ap_table_setn(r->headers_out, "Content-Length", ap_psprintf(r->pool, "%ld", clength)); + ap_table_setn(r->headers_out, "Content-Length", ap_psprintf(r->pool, "%qd", clength)); return 0; } |