83 |
* was opened before. |
* was opened before. |
84 |
*/ |
*/ |
85 |
close(data_fd); |
close(data_fd); |
86 |
send_r_bad_request(req); |
send_r_not_found(req); |
87 |
return 0; |
return 0; |
88 |
} |
} |
89 |
|
|
110 |
return data_fd; |
return data_fd; |
111 |
/* else, data_fd contains the fd of the file... */ |
/* else, data_fd contains the fd of the file... */ |
112 |
} |
} |
113 |
|
|
114 |
if (req->if_modified_since && |
if (req->if_modified_since && |
115 |
!modified_since(&(statbuf.st_mtime), req->if_modified_since)) { |
!modified_since(&(statbuf.st_mtime), req->if_modified_since)) { |
116 |
send_r_not_modified(req); |
send_r_not_modified(req); |
119 |
} |
} |
120 |
req->filesize = statbuf.st_size; |
req->filesize = statbuf.st_size; |
121 |
req->last_modified = statbuf.st_mtime; |
req->last_modified = statbuf.st_mtime; |
122 |
|
|
123 |
|
if (req->range_stop == 0) |
124 |
|
req->range_stop = statbuf.st_size; |
125 |
|
|
126 |
|
/* out of range! */ |
127 |
|
if (req->range_start > statbuf.st_size || |
128 |
|
req->range_stop > statbuf.st_size || |
129 |
|
req->range_stop < req->range_start) { |
130 |
|
send_r_range_unsatisfiable(req); |
131 |
|
close(data_fd); |
132 |
|
return 0; |
133 |
|
} |
134 |
|
|
135 |
if (req->method == M_HEAD || req->filesize == 0) { |
if (req->method == M_HEAD || req->filesize == 0) { |
136 |
send_r_request_ok(req); |
send_r_request_ok(req); |
138 |
return 0; |
return 0; |
139 |
} |
} |
140 |
|
|
141 |
if (req->filesize > MAX_FILE_MMAP) { |
if (req->range_stop > MAX_FILE_MMAP) { |
142 |
send_r_request_ok(req); /* All's well */ |
|
143 |
|
if ( req->range_start == 0 && req->range_stop == statbuf.st_size) |
144 |
|
send_r_request_ok(req); /* All's well */ |
145 |
|
else { |
146 |
|
/* if ranges were used, then lseek to the start given |
147 |
|
*/ |
148 |
|
if ( lseek( data_fd, req->range_start, SEEK_SET) == (off_t) -1) { |
149 |
|
close(data_fd); |
150 |
|
send_r_not_found(req); |
151 |
|
return 0; |
152 |
|
} |
153 |
|
send_r_request_partial(req);/* All's well */ |
154 |
|
} |
155 |
|
|
156 |
req->status = PIPE_READ; |
req->status = PIPE_READ; |
157 |
req->cgi_status = CGI_BUFFER; |
req->cgi_status = CGI_BUFFER; |
158 |
req->data_fd = data_fd; |
req->data_fd = data_fd; |
159 |
req_flush(req); /* this should *always* complete due to |
req_flush(req); /* this should *always* complete due to |
160 |
the size of the I/O buffers */ |
the size of the I/O buffers */ |
161 |
req->header_line = req->header_end = req->buffer; |
req->header_line = req->header_end = req->buffer; |
162 |
|
req->pipe_range_stop = req->range_stop; |
163 |
return 1; |
return 1; |
164 |
} |
} |
165 |
|
|
166 |
if (req->filesize == 0) { /* done */ |
if (req->range_stop == 0) { /* done */ |
167 |
send_r_request_ok(req); /* All's well *so far* */ |
send_r_request_ok(req); /* All's well *so far* */ |
168 |
close(data_fd); |
close(data_fd); |
169 |
return 1; |
return 1; |
190 |
} |
} |
191 |
req->data_mem = req->mmap_entry_var->mmap; |
req->data_mem = req->mmap_entry_var->mmap; |
192 |
#else |
#else |
193 |
req->data_mem = mmap(0, statbuf.st_size, PROT_READ, MAP_OPTIONS, data_fd, 0); |
req->data_mem = mmap(0, req->range_stop, PROT_READ, MAP_OPTIONS, data_fd, 0); |
194 |
#endif |
#endif |
195 |
close(data_fd); /* close data file */ |
close(data_fd); /* close data file */ |
196 |
|
|
199 |
return 0; |
return 0; |
200 |
} |
} |
201 |
|
|
202 |
send_r_request_ok(req); /* All's well */ |
if ( req->range_start == 0 && req->range_stop == statbuf.st_size) |
203 |
|
send_r_request_ok(req); /* All's well */ |
204 |
|
else |
205 |
|
send_r_request_partial(req);/* All's well */ |
206 |
|
|
207 |
bytes = BUFFER_SIZE - req->buffer_end; |
bytes = BUFFER_SIZE - req->buffer_end; |
208 |
|
|
209 |
/* bytes is now how much the buffer can hold |
/* bytes is now how much the buffer can hold |
210 |
* after the headers |
* after the headers |
211 |
*/ |
*/ |
212 |
|
req->filepos = req->range_start; |
213 |
|
|
214 |
if (bytes > 0) { |
if (bytes > 0) { |
215 |
if (bytes > req->filesize) |
if (bytes > req->range_stop - req->range_start) |
216 |
bytes = req->filesize; |
bytes = req->range_stop - req->range_start; |
217 |
|
|
218 |
if (setjmp(params->env) == 0) { |
if (setjmp(params->env) == 0) { |
219 |
params->handle_sigbus = 1; |
params->handle_sigbus = 1; |
220 |
memcpy(req->buffer + req->buffer_end, req->data_mem, bytes); |
memcpy(req->buffer + req->buffer_end, &req->data_mem[req->filepos], |
221 |
|
bytes); |
222 |
params->handle_sigbus = 0; |
params->handle_sigbus = 0; |
223 |
/* OK, SIGBUS **after** this point is very bad! */ |
/* OK, SIGBUS **after** this point is very bad! */ |
224 |
} else { |
} else { |
234 |
} |
} |
235 |
req->buffer_end += bytes; |
req->buffer_end += bytes; |
236 |
req->filepos += bytes; |
req->filepos += bytes; |
237 |
if (req->filesize == req->filepos) { |
if (req->range_stop == req->filepos) { |
238 |
req_flush(req); |
req_flush(req); |
239 |
req->status = DONE; |
req->status = DONE; |
240 |
} |
} |
311 |
int bytes_written; |
int bytes_written; |
312 |
volatile int bytes_to_write; |
volatile int bytes_to_write; |
313 |
|
|
314 |
bytes_to_write = req->filesize - req->filepos; |
bytes_to_write = req->range_stop - req->filepos; |
315 |
if (bytes_to_write > SOCKETBUF_SIZE) |
if (bytes_to_write > SOCKETBUF_SIZE) |
316 |
bytes_to_write = SOCKETBUF_SIZE; |
bytes_to_write = SOCKETBUF_SIZE; |
317 |
|
|
359 |
} |
} |
360 |
req->filepos += bytes_written; |
req->filepos += bytes_written; |
361 |
|
|
362 |
if (req->filepos == req->filesize) { /* EOF */ |
if (req->filepos == req->range_stop) { /* EOF */ |
363 |
return 0; |
return 0; |
364 |
} else |
} else |
365 |
return 1; /* more to do */ |
return 1; /* more to do */ |