[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:
Glenn Strauss 2016-04-01 17:38:29 +00:00 committed by Stefan Bühler
parent 47f3dbebe4
commit 36ab0587c0
2 changed files with 47 additions and 18 deletions

1
NEWS
View File

@ -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)

View File

@ -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) {