[stream] fstat() after open() to obtain file size
Common case is on non-empty files, and doing fstat() after open() eliminates ToC-ToU between stat() and then open(). While file size of the target file might still change, the fstat() is on the opened file, and can not be on different file (which was possible with stat()) From: Glenn Strauss <gstrauss@gluelogic.com> git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-1.4.x@3137 152afb58-edef-0310-8abb-c4023f1b3aa9
This commit is contained in:
parent
47f3dbebe4
commit
36ab0587c0
1
NEWS
1
NEWS
|
@ -60,6 +60,7 @@ NEWS
|
|||
* [mod_status] use snprintf() instead of sprintf()
|
||||
* pass buf size to li_tohex()
|
||||
* use li_[iu]tostrn() instead of li_[iu]tostr()
|
||||
* [stream] fstat() after open() to obtain file size
|
||||
|
||||
- 1.4.39 - 2016-01-02
|
||||
* [core] fix memset_s call (fixes #2698)
|
||||
|
|
64
src/stream.c
64
src/stream.c
|
@ -14,32 +14,38 @@
|
|||
# define O_BINARY 0
|
||||
#endif
|
||||
|
||||
int stream_open(stream *f, buffer *fn) {
|
||||
struct stat st;
|
||||
#ifdef HAVE_MMAP
|
||||
int fd;
|
||||
#elif defined __WIN32
|
||||
HANDLE *fh, *mh;
|
||||
void *p;
|
||||
/* don't want to block when open()ing a fifo */
|
||||
#if defined(O_NONBLOCK)
|
||||
# define FIFO_NONBLOCK O_NONBLOCK
|
||||
#else
|
||||
# define FIFO_NONBLOCK 0
|
||||
#endif
|
||||
|
||||
int stream_open(stream *f, buffer *fn) {
|
||||
|
||||
#ifdef HAVE_MMAP
|
||||
|
||||
struct stat st;
|
||||
int fd;
|
||||
|
||||
f->start = NULL;
|
||||
f->size = 0;
|
||||
|
||||
if (-1 == stat(fn->ptr, &st)) {
|
||||
if (-1 == (fd = open(fn->ptr, O_RDONLY | O_BINARY | FIFO_NONBLOCK))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (-1 == fstat(fd, &st)) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (0 == st.st_size) {
|
||||
/* empty file doesn't need a mapping */
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_MMAP
|
||||
if (-1 == (fd = open(fn->ptr, O_RDONLY | O_BINARY))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
f->start = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
|
||||
|
||||
close(fd);
|
||||
|
@ -49,7 +55,18 @@ int stream_open(stream *f, buffer *fn) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
f->size = st.st_size;
|
||||
return 0;
|
||||
|
||||
#elif defined __WIN32
|
||||
|
||||
HANDLE *fh, *mh;
|
||||
void *p;
|
||||
LARGE_INTEGER fsize;
|
||||
|
||||
f->start = NULL;
|
||||
f->size = 0;
|
||||
|
||||
fh = CreateFile(fn->ptr,
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ,
|
||||
|
@ -60,11 +77,21 @@ int stream_open(stream *f, buffer *fn) {
|
|||
|
||||
if (!fh) return -1;
|
||||
|
||||
if (0 != GetFileSizeEx(fh, &fsize)) {
|
||||
CloseHandle(fh);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (0 == fsize) {
|
||||
CloseHandle(fh);
|
||||
return 0;
|
||||
}
|
||||
|
||||
mh = CreateFileMapping( fh,
|
||||
NULL,
|
||||
PAGE_READONLY,
|
||||
(sizeof(off_t) > 4) ? st.st_size >> 32 : 0,
|
||||
st.st_size & 0xffffffff,
|
||||
(sizeof(off_t) > 4) ? fsize >> 32 : 0,
|
||||
fsize & 0xffffffff,
|
||||
NULL);
|
||||
|
||||
if (!mh) {
|
||||
|
@ -79,6 +106,7 @@ int stream_open(stream *f, buffer *fn) {
|
|||
(LPTSTR) &lpMsgBuf,
|
||||
0, NULL );
|
||||
*/
|
||||
CloseHandle(fh);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -91,13 +119,13 @@ int stream_open(stream *f, buffer *fn) {
|
|||
CloseHandle(fh);
|
||||
|
||||
f->start = p;
|
||||
f->size = (off_t)fsize;
|
||||
return 0;
|
||||
|
||||
#else
|
||||
# error no mmap found
|
||||
#endif
|
||||
|
||||
f->size = st.st_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stream_close(stream *f) {
|
||||
|
|
Loading…
Reference in New Issue