Browse Source

[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
svn/heads/lighttpd-1.4.x
Glenn Strauss 6 years ago
committed by Stefan Bühler
parent
commit
36ab0587c0
  1. 1
      NEWS
  2. 60
      src/stream.c

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)

60
src/stream.c

@ -14,32 +14,38 @@
# define O_BINARY 0
#endif
/* 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) {
struct stat st;
#ifdef HAVE_MMAP
struct stat st;
int fd;
#elif defined __WIN32
HANDLE *fh, *mh;
void *p;
#endif
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…
Cancel
Save