Building lighttpd on Windows¶
lighttpd cygwin is maintained as a set of packages available from cygwin
setup.exe and supports nearly all the same features of lighttpd available on unix-like systems. However, extra precautions may need to be taken to protect a _WIN32 system (see below), so you are strongly advised against using lighttpd cygwin in production.
lighttpd native _WIN32¶
lighttpd development prototype for native _WIN32 may be built static or shared (dll) using autotools or CMake with compiler toolchain mingw (cygwin or msys) or MS Visual Studio.
This is a prototype and you are strongly advised against using lighttpd native _WIN32 in production.
lighttpd native _WIN32 limitations¶
- not implemented
- server.c: no daemonize
- server.c: no multiple workers
- server.c: no lighttpd -1 one-shot mode
- log.c: no syslog option (no Windows Event Log)
- _WIN32 accepts both
\as path separators
lighttpd code has not been reviewed to normalize _WIN32
(possible security exposure)
- _WIN32 environment paths may begin with volume
C:/instead of with
(possible security exposure)
lighttpd code has not been reviewed to normalize _WIN32 paths.
lighttpd code assumes in many places that full path begins with
lighttpd might not work across multiple volumes.
- _WIN32 NTFS alternate data streams not rejected
(possible security exposure)
- _WIN32 filesystem functions do not properly handle UTF-8
(ASCII works when UNICODE is not defined; wide-char works with UNICODE)
Some UTF-8 to wide-char compat translation funcs provided in fs_win32.[ch],
but not comprehensive. unlink(), rmdir(), chdir() not provided, or others ...
(move, replace, etc and other use of _WIN32 ...A() funcs might need to be
replaced with funcs which convert from UTF-8 to wide-char and use ...W())
- NTFS fails attempt to rename files atomically if either file is open.
lighttpd uses this idiom in file caches (deflate.cache-dir disabled on _WIN32)
lighttpd mod_webdav will fail if a PUT or MOVE is attepted on open an file.
Many file operations other than read may fail due to this NTFS limitation.
- lighttpd mod_webdav has not been ported and will have multiple issues,
including but not limited to atomic file renames, non-ASCII UTF-8 file support
- lighttpd does not attempt to detect setCaseSensitiveInfo dir attribute
- SOCKET is (long long unsigned), not (int) as in POSIX file descriptors.
In practice (sample size n=1), SOCKET appears to be < INT_MAX, except for
INVALID_SOCKET ((long long unsigned)-1), which casts back to (int)-1.
While it does not appear necessary to rewrite all code to use SOCKET instead
of int, it would be nice that IFF true, that it be documented by Microsoft.
Both the size of the type (64-bit) and the sign (unsigned) is unfriendly to
porting code. It is suggested that historically SOCKET was a pointer value
cast to (uintptr_t) (good job with type-safety $MS!). In 32-bit, int and
pointers are the same size, but not in 64-bit. Perhaps this was changed at
some point in $MS evolution, but is not well documented, as at least initial
assignments are smallish integers in 200's and 300's. $MS is able to
distinguish between file descriptors (int) and (SOCKET) since both are
supported by SetHandleInformation(), ReadFile(), WriteFile(), so we can
conclude that $MS did not propagate that logic elsewhere, but probably could.
((HANDLE)(uint64_t)sockfd); ((HANDLE)_get_osfhandle(fd)) (e.g. file and pipes)
- SOCKET and file descriptors are not allowed as lowest available integer,
so using an array indexed by file descriptors is not a good pattern to apply.
- select() and WSAPoll() work only with SOCKET, not with files or pipes.
(see WaitForSingleObject() WaitForMultipleObjects() and related functions)
- select() is not a bitmap; client code around select() often needs to be
reworked.  The macros such as FD_ISSET must be applied to SOCKET, and not
to arbitrary integer in range from [0,FD_SETSIZE)
- filesystem redirection (stdin/stdout/stderr) to sockets is possible, but:
- filehandles must be inheritable (default)
- sockets must be non-overlapped (not default)
- socket() creates sockets with WSA_FLAG_OVERLAPPED
- WSASocket() has flag option to omit WSA_FLAG_OVERLAPPED
- programs generally need SYSTEMROOT defined in the environment to run properly
- #define WIN32_LEAN_AND_MEAN must be defined before #include <windows.h>
or else you may get (undesirable) winsock 1.1 header visibility
For some apps, #include <winsock2.h> is sufficient instead of #include <windows.h>
Must link with -lws2_32
#pragma comment(lib, "ws2_32.lib")
- connect() on non-blocking socket errors with WSAGetLastError() WSAWOULDBLOCK,
- dup() and dup2() can not be used on SOCKET (see WSADuplicateSocket())
- dup2() does not return the newfd; incompatible interface
- stat() on a directory fails if string has trailing
- stat() returns ENOENT instead of ENOTDIR for CGI PATH_INFO,
- stat() fails on //?/c:/... paths
- error codes: WSAGetLastError() for sockets; do not check errno
- error codes: GetLastError() (except for sockets), and sometimes errno
- Microsoft NTFS does not allow move/rename file operations on open files.
(Attempts to do so result in Permission denied; file already in use.)
A typical POSIX idiom of atomic rename fails on NTFS if either old or new
file is open. This breaks in lighttpd in numerous places where a cache is
updated and the new file is kept open during the rename, and then served to
the client. Forcing the file to be closed and then reopened around the
rename introduces a race condition in what is ultimately sent to the client.
(While this race is introduced in mod_deflate cache, mod_webdav and other
modules might still suffer/fail from this NTFS limitation.)
- UCRT <sys/types.h> unconditionally defines off_t as long (4 bytes on _WIN32)
if _CRT_DECLARE_NONSTDC_NAMES is defined. Any application or library which
supports large files and expects 64-bit off_t needs to take steps to
workaround this (e.g. define off_t, _off_t, _OFF_T_DEFINED in advance).
Select, FD_SET, and FD_XXX Macros
Since sockets are not represented by the UNIX-style, small, non-negative integer, the implementation of the select function was changed in Windows Sockets. Each set of sockets is still represented by the FD_SET structure, but instead of being stored as a bitmask, the set is implemented as an array of sockets. To avoid potential problems, applications must adhere to the use of the FD_XXX macros to set, initialize, clear, and check the FD_SET structures.