diff --git a/.github/workflows/cpp-linter.yml b/.github/workflows/cpp-linter.yml
index 006dc1ed6e..9f166e1027 100644
--- a/.github/workflows/cpp-linter.yml
+++ b/.github/workflows/cpp-linter.yml
@@ -42,6 +42,9 @@ jobs:
,clang-analyzer-*
,cppcoreguidelines-*
,-cppcoreguidelines-avoid-magic-numbers
+ ,-cppcoreguidelines-init-variables
+ ,-readability-identifier-length
+ ,-readability-isolate-declaration
,-readability-magic-numbers
- name: Fail fast?!
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index d7fefad519..46605afde1 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -90,7 +90,6 @@ jobs:
run: |
brew install \
automake \
- dylibbundler \
sdl2 \
sdl2_mixer \
sdl2_net \
diff --git a/configure.ac b/configure.ac
index 20df4620fc..b368790522 100644
--- a/configure.ac
+++ b/configure.ac
@@ -205,7 +205,7 @@ CFLAGS="$CFLAGS $SDL_CFLAGS ${SAMPLERATE_CFLAGS:-} ${PNG_CFLAGS:-} ${FLUIDSYNTH_
LDFLAGS="$LDFLAGS $SDL_LIBS ${SAMPLERATE_LIBS:-} ${PNG_LIBS:-} ${FLUIDSYNTH_LIBS:-} ${LIBZ_LIBS:-}"
case "$host" in
*-*-mingw* | *-*-cygwin* | *-*-msvc* )
- LDFLAGS="$LDFLAGS -lwinmm"
+ LDFLAGS="$LDFLAGS -lwinmm -lshlwapi"
;;
*)
esac
diff --git a/opl/opl_sdl.c b/opl/opl_sdl.c
index f15af6c286..2517de15c0 100644
--- a/opl/opl_sdl.c
+++ b/opl/opl_sdl.c
@@ -432,7 +432,7 @@ static void WriteRegister(unsigned int reg_num, unsigned int value)
if ((value & 0x20) == 0)
{
- timer1.enabled = (value & 0x02) != 0;
+ timer2.enabled = (value & 0x02) != 0;
OPLTimer_CalculateEndTime(&timer2);
}
}
diff --git a/pkg/Makefile.am b/pkg/Makefile.am
index 823851b8f0..3a287b2464 100644
--- a/pkg/Makefile.am
+++ b/pkg/Makefile.am
@@ -21,5 +21,5 @@ win32/GNUmakefile \
win32/cp-with-libs \
win32/README
-EXTRA_DIST=$(OSX_FILES) $(WIN32_FILES)
+EXTRA_DIST=style.html $(OSX_FILES) $(WIN32_FILES)
diff --git a/pkg/osx/GNUmakefile b/pkg/osx/GNUmakefile
index 94e20830f1..55d7ac8101 100644
--- a/pkg/osx/GNUmakefile
+++ b/pkg/osx/GNUmakefile
@@ -18,12 +18,6 @@ DMG=$(PACKAGE_TARNAME)-$(PACKAGE_VERSION)-$(POSTFIX).dmg
TOPLEVEL=../..
TOPLEVEL_DOCS=$(patsubst %,../../%,$(DOC_FILES))
-ifeq (, $(shell which dylibbundler))
- CP=./cp-with-libs
-else
- CP=cp
-endif
-
# DMG file containing package:
$(DMG) : tmp.dmg
@@ -75,26 +69,17 @@ $(STAGING_DIR): launcher $(TOPLEVEL_DOCS) app.icns wadfile.icns
cp launcher "$(APP_BIN_DIR)"
$(STRIP) "$(APP_BIN_DIR)/launcher"
- $(CP) $(TOPLEVEL)/src/$(PROGRAM_PREFIX)doom "$(APP_BIN_DIR)"
+ ./cp-with-libs $(TOPLEVEL)/src/$(PROGRAM_PREFIX)doom "$(APP_BIN_DIR)"
$(STRIP) "$(APP_BIN_DIR)/$(PROGRAM_PREFIX)doom"
- $(CP) $(TOPLEVEL)/src/$(PROGRAM_PREFIX)heretic "$(APP_BIN_DIR)"
+ ./cp-with-libs $(TOPLEVEL)/src/$(PROGRAM_PREFIX)heretic "$(APP_BIN_DIR)"
$(STRIP) "$(APP_BIN_DIR)/$(PROGRAM_PREFIX)heretic"
- $(CP) $(TOPLEVEL)/src/$(PROGRAM_PREFIX)hexen "$(APP_BIN_DIR)"
+ ./cp-with-libs $(TOPLEVEL)/src/$(PROGRAM_PREFIX)hexen "$(APP_BIN_DIR)"
$(STRIP) "$(APP_BIN_DIR)/$(PROGRAM_PREFIX)hexen"
- $(CP) $(TOPLEVEL)/src/$(PROGRAM_PREFIX)strife "$(APP_BIN_DIR)"
+ ./cp-with-libs $(TOPLEVEL)/src/$(PROGRAM_PREFIX)strife "$(APP_BIN_DIR)"
$(STRIP) "$(APP_BIN_DIR)/$(PROGRAM_PREFIX)strife"
- $(CP) $(TOPLEVEL)/src/$(PROGRAM_PREFIX)setup "$(APP_BIN_DIR)"
+ ./cp-with-libs $(TOPLEVEL)/src/$(PROGRAM_PREFIX)setup "$(APP_BIN_DIR)"
$(STRIP) "$(APP_BIN_DIR)/$(PROGRAM_PREFIX)setup"
- -dylibbundler --bundle-deps --overwrite-files \
- --install-path "@executable_path/" \
- --dest-dir "$(APP_BIN_DIR)" \
- --fix-file "$(APP_BIN_DIR)/$(PROGRAM_PREFIX)doom" \
- --fix-file "$(APP_BIN_DIR)/$(PROGRAM_PREFIX)heretic" \
- --fix-file "$(APP_BIN_DIR)/$(PROGRAM_PREFIX)hexen" \
- --fix-file "$(APP_BIN_DIR)/$(PROGRAM_PREFIX)strife" \
- --fix-file "$(APP_BIN_DIR)/$(PROGRAM_PREFIX)setup"
-
$(TOPLEVEL)/man/simplecpp -DPRECOMPILED -D__MACOSX__ \
-DDOOM -DHERETIC -DHEXEN -DSTRIFE \
< $(TOPLEVEL)/man/INSTALL.template \
diff --git a/pkg/osx/cp-with-libs b/pkg/osx/cp-with-libs
index 04fb5bc6cb..f4869063f4 100755
--- a/pkg/osx/cp-with-libs
+++ b/pkg/osx/cp-with-libs
@@ -27,6 +27,9 @@ is_sys_lib() {
/System/*)
true
;;
+ /usr/local/*) # homebrew/manual install
+ false
+ ;;
/usr/*)
true
;;
@@ -54,7 +57,7 @@ install_with_deps() {
if [ -e "$dest_file" ]; then
return
- fi
+ fi
echo "Installing $bin_name..."
@@ -65,7 +68,6 @@ install_with_deps() {
# Copy libraries that this file depends on:
otool -L "$src_file" | tail -n +2 | sed 's/^.//; s/ (.*//' | while read; do
-
# Don't copy system libraries
if is_sys_lib "$REPLY"; then
@@ -92,6 +94,11 @@ install_with_deps() {
if is_dylib "$dest_file"; then
install_name_tool -id "@executable_path/$bin_name" "$dest_file"
fi
+
+ # The install_name_tool calls above break signatures. Recent versions
+ # of macOS make signatures mandatory, even if just ad-hoc ones.
+ codesign --remove-signature "$dest_file"
+ codesign --force -s - "$dest_file" # ad-hoc signature
}
# Install the file, and recursively install any libraries:
diff --git a/pkg/style.html b/pkg/style.html
new file mode 100644
index 0000000000..4ae291a3c1
--- /dev/null
+++ b/pkg/style.html
@@ -0,0 +1,48 @@
+
+
+
+
+
diff --git a/pkg/win32/GNUmakefile b/pkg/win32/GNUmakefile
index e8b69b36ab..0c0900f57a 100644
--- a/pkg/win32/GNUmakefile
+++ b/pkg/win32/GNUmakefile
@@ -9,6 +9,8 @@ else
POSTFIX=win32
endif
+PANDOC_FLAGS = -f gfm -s --template=default.html5 -H ../style.html
+
DOOM_ZIP=$(PROGRAM_PREFIX)doom-$(PACKAGE_VERSION)-$(POSTFIX).zip
HERETIC_ZIP=$(PROGRAM_PREFIX)heretic-$(PACKAGE_VERSION)-$(POSTFIX).zip
HEXEN_ZIP=$(PROGRAM_PREFIX)hexen-$(PACKAGE_VERSION)-$(POSTFIX).zip
@@ -32,12 +34,12 @@ $(STRIFE_ZIP): staging-strife hook-strife
# Special hooks to custom modify files for particular games.
hook-doom: staging-doom
- -pandoc -f gfm -s -o $
// @category compat
//
- // Emulate a specific version of Doom. Valid values are "1.2",
- // "1.666", "1.7", "1.8", "1.9", "ultimate", "final", "final2",
- // "hacx" and "chex".
+ // Emulate a specific version of Doom. Valid values are "1.2",
+ // "1.5", "1.666", "1.7", "1.8", "1.9", "ultimate", "final",
+ // "final2", "hacx" and "chex".
//
p = M_CheckParmWithArgs("-gameversion", 1);
diff --git a/src/doom/p_enemy.c b/src/doom/p_enemy.c
index ad5a62ab92..010b899157 100644
--- a/src/doom/p_enemy.c
+++ b/src/doom/p_enemy.c
@@ -180,7 +180,7 @@ boolean P_CheckMeleeRange (mobj_t* actor)
pl = actor->target;
dist = P_AproxDistance (pl->x-actor->x, pl->y-actor->y);
- if (gameversion <= exe_doom_1_2)
+ if (gameversion < exe_doom_1_5)
range = MELEERANGE;
else
range = MELEERANGE-20*FRACUNIT+pl->info->radius;
@@ -958,7 +958,7 @@ void A_SargAttack (mobj_t* actor)
A_FaceTarget (actor);
- if (gameversion > exe_doom_1_2)
+ if (gameversion >= exe_doom_1_5)
{
if (!P_CheckMeleeRange (actor))
return;
diff --git a/src/doom/p_inter.c b/src/doom/p_inter.c
index 42ccc5e924..1198d7290b 100644
--- a/src/doom/p_inter.c
+++ b/src/doom/p_inter.c
@@ -979,7 +979,7 @@ P_DamageMobj
target->reactiontime = 0; // we're awake now...
if ( (!target->threshold || target->type == MT_VILE)
- && source && (source != target || gameversion <= exe_doom_1_2)
+ && source && (source != target || gameversion < exe_doom_1_5)
&& source->type != MT_VILE)
{
// if not intent on another player,
diff --git a/src/i_glob.c b/src/i_glob.c
index 90c531076e..8b7612837b 100644
--- a/src/i_glob.c
+++ b/src/i_glob.c
@@ -24,8 +24,7 @@
#include "m_misc.h"
#include "config.h"
-#if defined(_MSC_VER)
-// For Visual C++, we need to include the win_opendir module.
+#if defined(_WIN32)
#include
#define S_ISDIR(m) (((m)& S_IFMT) == S_IFDIR)
#elif defined(HAVE_DIRENT_H)
@@ -102,7 +101,6 @@ glob_t *I_StartMultiGlob(const char *directory, int flags,
int num_globs;
glob_t *result;
va_list args;
- char *directory_native;
globs = malloc(sizeof(char *));
if (globs == NULL)
@@ -141,18 +139,15 @@ glob_t *I_StartMultiGlob(const char *directory, int flags,
return NULL;
}
- directory_native = M_ConvertUtf8ToSysNativeMB(directory);
-
- result->dir = opendir(directory_native);
+ result->dir = opendir(directory);
if (result->dir == NULL)
{
FreeStringList(globs, num_globs);
free(result);
- free(directory_native);
return NULL;
}
- result->directory = directory_native;
+ result->directory = M_StringDuplicate(directory);
result->globs = globs;
result->num_globs = num_globs;
result->flags = flags;
@@ -246,7 +241,6 @@ static boolean MatchesAnyGlob(const char *name, glob_t *glob)
static char *NextGlob(glob_t *glob)
{
struct dirent *de;
- char *temp, *ret;
do
{
@@ -259,13 +253,7 @@ static char *NextGlob(glob_t *glob)
|| !MatchesAnyGlob(de->d_name, glob));
// Return the fully-qualified path, not just the bare filename.
- temp = M_StringJoin(glob->directory, DIR_SEPARATOR_S, de->d_name, NULL);
-
- ret = M_ConvertSysNativeMBToUtf8(temp);
-
- free(temp);
-
- return ret;
+ return M_StringJoin(glob->directory, DIR_SEPARATOR_S, de->d_name, NULL);
}
static void ReadAllFilenames(glob_t *glob)
diff --git a/src/i_video.c b/src/i_video.c
index 2e8a1baea7..8bd95b78ea 100644
--- a/src/i_video.c
+++ b/src/i_video.c
@@ -87,8 +87,6 @@ static SDL_Rect blit_rect = {
};
#endif
-static uint32_t pixel_format;
-
// palette
#ifdef CRISPY_TRUECOLOR
@@ -733,7 +731,7 @@ static void CreateUpscaledTexture(boolean force)
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
new_texture = SDL_CreateTexture(renderer,
- pixel_format,
+ SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_TARGET,
w_upscale*SCREENWIDTH,
h_upscale*SCREENHEIGHT);
@@ -866,14 +864,16 @@ void I_FinishUpdate (void)
}
// Blit from the paletted 8-bit screen buffer to the intermediate
- // 32-bit RGBA buffer that we can load into the texture.
+ // 32-bit RGBA buffer and update the intermediate texture with the
+ // contents of the RGBA buffer.
+ SDL_LockTexture(texture, &blit_rect, &argbbuffer->pixels,
+ &argbbuffer->pitch);
SDL_LowerBlit(screenbuffer, &blit_rect, argbbuffer, &blit_rect);
-#endif
-
- // Update the intermediate texture with the contents of the RGBA buffer.
-
+ SDL_UnlockTexture(texture);
+#else
SDL_UpdateTexture(texture, NULL, argbbuffer->pixels, argbbuffer->pitch);
+#endif
// Make sure the pillarboxes are kept clear each frame.
@@ -1005,6 +1005,7 @@ void I_SetPalette (byte *doompalette)
// controller only supports 6 bits of accuracy.
// [crispy] intermediate gamma levels
+ palette[i].a = 0xFFU;
palette[i].r = gamma2table[crispy->gamma][*doompalette++] & ~3;
palette[i].g = gamma2table[crispy->gamma][*doompalette++] & ~3;
palette[i].b = gamma2table[crispy->gamma][*doompalette++] & ~3;
@@ -1456,10 +1457,6 @@ static void SetVideoMode(void)
{
int w, h;
int x, y;
-#ifndef CRISPY_TRUECOLOR
- unsigned int rmask, gmask, bmask, amask;
-#endif
- int bpp;
int window_flags = 0, renderer_flags = 0;
SDL_DisplayMode mode;
@@ -1517,8 +1514,6 @@ static void SetVideoMode(void)
SDL_GetError());
}
- pixel_format = SDL_GetWindowPixelFormat(screen);
-
SDL_SetWindowMinimumSize(screen, SCREENWIDTH, actualheight);
I_InitWindowTitle();
@@ -1635,12 +1630,10 @@ static void SetVideoMode(void)
if (argbbuffer == NULL)
{
- SDL_PixelFormatEnumToMasks(pixel_format, &bpp,
- &rmask, &gmask, &bmask, &amask);
- argbbuffer = SDL_CreateRGBSurface(0,
- SCREENWIDTH, SCREENHEIGHT, bpp,
- rmask, gmask, bmask, amask);
#ifdef CRISPY_TRUECOLOR
+ argbbuffer = SDL_CreateRGBSurfaceWithFormat(
+ 0, SCREENWIDTH, SCREENHEIGHT, 32, SDL_PIXELFORMAT_ARGB8888);
+
SDL_FillRect(argbbuffer, NULL, I_MapRGB(0xff, 0x0, 0x0));
redpane = SDL_CreateTextureFromSurface(renderer, argbbuffer);
SDL_SetTextureBlendMode(redpane, SDL_BLENDMODE_BLEND);
@@ -1668,8 +1661,12 @@ static void SetVideoMode(void)
SDL_FillRect(argbbuffer, NULL, I_MapRGB(0x96, 0x6e, 0x0)); // 150, 110, 0
orngpane = SDL_CreateTextureFromSurface(renderer, argbbuffer);
SDL_SetTextureBlendMode(orngpane, SDL_BLENDMODE_BLEND);
+#else
+ // pixels and pitch will be filled with the texture's values
+ // in I_FinishUpdate()
+ argbbuffer = SDL_CreateRGBSurfaceWithFormatFrom(
+ NULL, w, h, 0, 0, SDL_PIXELFORMAT_ARGB8888);
#endif
- SDL_FillRect(argbbuffer, NULL, 0);
}
if (texture != NULL)
@@ -1688,7 +1685,7 @@ static void SetVideoMode(void)
// is going to change frequently.
texture = SDL_CreateTexture(renderer,
- pixel_format,
+ SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_STREAMING,
SCREENWIDTH, SCREENHEIGHT);
@@ -1898,9 +1895,6 @@ void I_ReInitGraphics (int reinit)
// [crispy] re-set rendering resolution and re-create framebuffers
if (reinit & REINIT_FRAMEBUFFERS)
{
- unsigned int rmask, gmask, bmask, amask;
- int unused_bpp;
-
I_GetScreenDimensions();
#ifndef CRISPY_TRUECOLOR
@@ -1919,11 +1913,9 @@ void I_ReInitGraphics (int reinit)
#endif
SDL_FreeSurface(argbbuffer);
- SDL_PixelFormatEnumToMasks(pixel_format, &unused_bpp,
- &rmask, &gmask, &bmask, &amask);
- argbbuffer = SDL_CreateRGBSurface(0,
- SCREENWIDTH, SCREENHEIGHT, 32,
- rmask, gmask, bmask, amask);
+ argbbuffer = SDL_CreateRGBSurfaceWithFormat(0,
+ SCREENWIDTH, SCREENHEIGHT, 32,
+ SDL_PIXELFORMAT_ARGB8888);
#ifndef CRISPY_TRUECOLOR
// [crispy] re-set the framebuffer pointer
I_VideoBuffer = screenbuffer->pixels;
@@ -1968,7 +1960,7 @@ void I_ReInitGraphics (int reinit)
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest");
texture = SDL_CreateTexture(renderer,
- pixel_format,
+ SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_STREAMING,
SCREENWIDTH, SCREENHEIGHT);
diff --git a/src/m_misc.c b/src/m_misc.c
index ea531ea3ac..28882d0b03 100644
--- a/src/m_misc.c
+++ b/src/m_misc.c
@@ -28,23 +28,15 @@
#define WIN32_LEAN_AND_MEAN
#include
#include
-#ifdef _MSC_VER
#include
-#endif
#else
#include
#endif
#include "doomtype.h"
-#include "deh_str.h"
-
-#include "i_swap.h"
#include "i_system.h"
-#include "i_video.h"
#include "m_misc.h"
-#include "v_video.h"
-#include "w_wad.h"
#include "z_zone.h"
#ifdef _WIN32
@@ -122,16 +114,6 @@ char *M_ConvertWideToUtf8(const wchar_t *wstr)
return ConvertWideToMultiByte(wstr, CP_UTF8);
}
-static wchar_t *ConvertSysNativeMBToWide(const char *str)
-{
- return ConvertMultiByteToWide(str, CP_ACP);
-}
-
-static char *ConvertWideToSysNativeMB(const wchar_t *wstr)
-{
- return ConvertWideToMultiByte(wstr, CP_ACP);
-}
-
// Convert UTF8 string to a wide string. The result is newly allocated and must
// be freed by the caller after use.
@@ -141,58 +123,6 @@ wchar_t *M_ConvertUtf8ToWide(const char *str)
}
#endif
-// Convert multibyte string in system encoding to UTF8. The result is newly
-// allocated and must be freed by the caller after use.
-
-char *M_ConvertSysNativeMBToUtf8(const char *str)
-{
-#ifdef _WIN32
- char *ret = NULL;
- wchar_t *wstr = NULL;
-
- wstr = ConvertSysNativeMBToWide(str);
-
- if (!wstr)
- {
- return NULL;
- }
-
- ret = M_ConvertWideToUtf8(wstr);
-
- free(wstr);
-
- return ret;
-#else
- return M_StringDuplicate(str);
-#endif
-}
-
-// Convert UTF8 string to multibyte string in system encoding. The result is
-// newly allocated and must be freed by the caller after use.
-
-char *M_ConvertUtf8ToSysNativeMB(const char *str)
-{
-#ifdef _WIN32
- char *ret = NULL;
- wchar_t *wstr = NULL;
-
- wstr = M_ConvertUtf8ToWide(str);
-
- if (!wstr)
- {
- return NULL;
- }
-
- ret = ConvertWideToSysNativeMB(wstr);
-
- free(wstr);
-
- return ret;
-#else
- return M_StringDuplicate(str);
-#endif
-}
-
FILE *M_fopen(const char *filename, const char *mode)
{
#ifdef _WIN32
diff --git a/src/m_misc.h b/src/m_misc.h
index 7b9e72cc33..6dc18ccfa3 100644
--- a/src/m_misc.h
+++ b/src/m_misc.h
@@ -30,8 +30,6 @@
wchar_t *M_ConvertUtf8ToWide(const char *str);
char *M_ConvertWideToUtf8(const wchar_t *wstr);
#endif
-char *M_ConvertUtf8ToSysNativeMB(const char *str);
-char *M_ConvertSysNativeMBToUtf8(const char *str);
FILE *M_fopen(const char *filename, const char *mode);
int M_remove(const char *path);
diff --git a/src/net_server.c b/src/net_server.c
index 42ab0d9f6c..9374b64ec7 100644
--- a/src/net_server.c
+++ b/src/net_server.c
@@ -383,11 +383,35 @@ static net_client_t *NET_SV_Controller(void)
return best;
}
+typedef enum
+{
+ RANGE_LOCALHOST, // Same process or 127.x
+ RANGE_PRIVATE, // RFC 1918
+ RANGE_PUBLIC, // The public Internet
+} ip_range_t;
+
+static ip_range_t ClientAddressRange(const char *addr)
+{
+ if (!strcmp(addr, "local client")
+ || M_StringStartsWith(addr, "127."))
+ {
+ return RANGE_LOCALHOST;
+ }
+ if (M_StringStartsWith(addr, "10.")
+ || M_StringStartsWith(addr, "192.168."))
+ {
+ return RANGE_PRIVATE;
+ }
+ return RANGE_PUBLIC;
+}
+
static void NET_SV_SendWaitingData(net_client_t *client)
{
net_waitdata_t wait_data;
net_packet_t *packet;
net_client_t *controller;
+ ip_range_t client_range, player_range;
+ const char *addr;
int i;
NET_SV_AssignPlayers();
@@ -416,6 +440,11 @@ static void NET_SV_SendWaitingData(net_client_t *client)
sizeof(sha1_digest_t));
wait_data.is_freedoom = controller->is_freedoom;
+ // We only send IP addresses to locally-connected clients (including
+ // the 127.* loopback range):
+ addr = NET_AddrToString(client->connection.addr);
+ client_range = ClientAddressRange(addr);
+
// set name and address of each player:
for (i = 0; i < wait_data.num_players; ++i)
@@ -423,9 +452,28 @@ static void NET_SV_SendWaitingData(net_client_t *client)
M_StringCopy(wait_data.player_names[i],
sv_players[i]->name,
MAXPLAYERNAME);
- M_StringCopy(wait_data.player_addrs[i],
- NET_AddrToString(sv_players[i]->addr),
- MAXPLAYERNAME);
+
+ // For privacy, only local clients or those on a LAN get to see
+ // addresses. Public clients only get to see their own address,
+ // though we do reveal localhost addresses since they're harmless,
+ // and we do reveal when a client is connected via LAN.
+ addr = NET_AddrToString(sv_players[i]->addr);
+ player_range = ClientAddressRange(addr);
+ if (client_range == RANGE_LOCALHOST || client_range == RANGE_PRIVATE
+ || i == wait_data.consoleplayer || player_range == RANGE_LOCALHOST)
+ {
+ M_StringCopy(wait_data.player_addrs[i], addr, MAXPLAYERNAME);
+ }
+ else if (player_range == RANGE_PRIVATE)
+ {
+ M_snprintf(wait_data.player_addrs[i], MAXPLAYERNAME,
+ "[LAN player]");
+ }
+ else
+ {
+ M_snprintf(wait_data.player_addrs[i], MAXPLAYERNAME,
+ "[address hidden]");
+ }
}
// Construct packet:
diff --git a/textscreen/txt_sdl.c b/textscreen/txt_sdl.c
index 42480f4869..eed6167676 100644
--- a/textscreen/txt_sdl.c
+++ b/textscreen/txt_sdl.c
@@ -88,21 +88,21 @@ static const short code_page_to_unicode[] = CODE_PAGE_TO_UNICODE;
static const SDL_Color ega_colors[] =
{
{0x00, 0x00, 0x00, 0xff}, // 0: Black
- {0x00, 0x00, 0xa8, 0xff}, // 1: Blue
- {0x00, 0xa8, 0x00, 0xff}, // 2: Green
- {0x00, 0xa8, 0xa8, 0xff}, // 3: Cyan
- {0xa8, 0x00, 0x00, 0xff}, // 4: Red
- {0xa8, 0x00, 0xa8, 0xff}, // 5: Magenta
- {0xa8, 0x54, 0x00, 0xff}, // 6: Brown
- {0xa8, 0xa8, 0xa8, 0xff}, // 7: Grey
- {0x54, 0x54, 0x54, 0xff}, // 8: Dark grey
- {0x54, 0x54, 0xfe, 0xff}, // 9: Bright blue
- {0x54, 0xfe, 0x54, 0xff}, // 10: Bright green
- {0x54, 0xfe, 0xfe, 0xff}, // 11: Bright cyan
- {0xfe, 0x54, 0x54, 0xff}, // 12: Bright red
- {0xfe, 0x54, 0xfe, 0xff}, // 13: Bright magenta
- {0xfe, 0xfe, 0x54, 0xff}, // 14: Yellow
- {0xfe, 0xfe, 0xfe, 0xff}, // 15: Bright white
+ {0x00, 0x00, 0xaa, 0xff}, // 1: Blue
+ {0x00, 0xaa, 0x00, 0xff}, // 2: Green
+ {0x00, 0xaa, 0xaa, 0xff}, // 3: Cyan
+ {0xaa, 0x00, 0x00, 0xff}, // 4: Red
+ {0xaa, 0x00, 0xaa, 0xff}, // 5: Magenta
+ {0xaa, 0x55, 0x00, 0xff}, // 6: Brown
+ {0xaa, 0xaa, 0xaa, 0xff}, // 7: Grey
+ {0x55, 0x55, 0x55, 0xff}, // 8: Dark grey
+ {0x55, 0x55, 0xff, 0xff}, // 9: Bright blue
+ {0x55, 0xff, 0x55, 0xff}, // 10: Bright green
+ {0x55, 0xff, 0xff, 0xff}, // 11: Bright cyan
+ {0xff, 0x55, 0x55, 0xff}, // 12: Bright red
+ {0xff, 0x55, 0xff, 0xff}, // 13: Bright magenta
+ {0xff, 0xff, 0x55, 0xff}, // 14: Yellow
+ {0xff, 0xff, 0xff, 0xff}, // 15: Bright white
};
#ifdef _WIN32
diff --git a/win32/win_opendir.c b/win32/win_opendir.c
index b2f67805fc..a03489c9cc 100644
--- a/win32/win_opendir.c
+++ b/win32/win_opendir.c
@@ -1,336 +1,425 @@
-//
-// 03/10/2006 James Haley
-//
-// For this module only:
-// This code is public domain. No change sufficient enough to constitute a
-// significant or original work has been made, and thus it remains as such.
-//
-//
-// DESCRIPTION:
-//
-// Implementation of POSIX opendir for Visual C++.
-// Derived from the MinGW C Library Extensions Source (released to the
-// public domain). As with other Win32 modules, don't include most DOOM
-// headers into this or conflicts will occur.
-//
-// Original Header:
-//
-// * dirent.c
-// * This file has no copyright assigned and is placed in the Public Domain.
-// * This file is a part of the mingw-runtime package.
-// * No warranty is given; refer to the file DISCLAIMER within the package.
-// *
-// * Derived from DIRLIB.C by Matt J. Weinstein
-// * This note appears in the DIRLIB.H
-// * DIRLIB.H by M. J. Weinstein Released to public domain 1-Jan-89
-// *
-// * Updated by Jeremy Bettis
-// * Significantly revised and rewinddir, seekdir and telldir added by Colin
-// * Peters
-//
-
-#ifndef _MSC_VER
-#error i_opndir.c is for Microsoft Visual C++ only
-#endif
+/*
+MIT License
+Copyright (c) 2019 win32ports
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#ifdef _WIN32
+
+#include "win_opendir.h"
-#include
+#include
#include
-#include
#define WIN32_LEAN_AND_MEAN
-#include /* for GetFileAttributes */
+#include
+#include
-#include
-#define SUFFIX _T("*")
-#define SLASH _T("\\")
+#ifdef _MSC_VER
+#pragma comment(lib, "Shlwapi.lib")
+#endif
-#include "win_opendir.h"
+#ifndef NTFS_MAX_PATH
+#define NTFS_MAX_PATH 32768
+#endif /* NTFS_MAX_PATH */
+
+#ifndef FSCTL_GET_REPARSE_POINT
+#define FSCTL_GET_REPARSE_POINT 0x900a8
+#endif /* FSCTL_GET_REPARSE_POINT */
+
+#ifndef FILE_NAME_NORMALIZED
+#define FILE_NAME_NORMALIZED 0
+#endif /* FILE_NAME_NORMALIZED */
-//
-// opendir
-//
-// Returns a pointer to a DIR structure appropriately filled in to begin
-// searching a directory.
-//
-DIR *opendir(const _TCHAR *szPath)
+int closedir(DIR *dirp)
{
- DIR *nd;
- unsigned int rc;
- _TCHAR szFullPath[MAX_PATH];
-
- errno = 0;
-
- if(!szPath)
- {
- errno = EFAULT;
- return (DIR *)0;
- }
-
- if(szPath[0] == _T('\0'))
- {
- errno = ENOTDIR;
- return (DIR *)0;
- }
-
- /* Attempt to determine if the given path really is a directory. */
- rc = GetFileAttributes(szPath);
- if(rc == (unsigned int)-1)
- {
- /* call GetLastError for more error info */
- errno = ENOENT;
- return (DIR *)0;
- }
- if(!(rc & FILE_ATTRIBUTE_DIRECTORY))
- {
- /* Error, entry exists but not a directory. */
- errno = ENOTDIR;
- return (DIR *)0;
- }
-
- /* Make an absolute pathname. */
- _tfullpath(szFullPath, szPath, MAX_PATH);
-
- /* Allocate enough space to store DIR structure and the complete
- * directory path given. */
- nd = (DIR *)(malloc(sizeof(DIR) + (_tcslen(szFullPath)
- + _tcslen(SLASH)
- + _tcslen(SUFFIX) + 1)
- * sizeof(_TCHAR)));
-
- if(!nd)
- {
- /* Error, out of memory. */
- errno = ENOMEM;
- return (DIR *)0;
- }
-
- /* Create the search expression. */
- _tcscpy(nd->dd_name, szFullPath);
-
- /* Add on a slash if the path does not end with one. */
- if(nd->dd_name[0] != _T('\0')
- && _tcsrchr(nd->dd_name, _T('/')) != nd->dd_name
- + _tcslen(nd->dd_name) - 1
- && _tcsrchr(nd->dd_name, _T('\\')) != nd->dd_name
- + _tcslen(nd->dd_name) - 1)
- {
- _tcscat(nd->dd_name, SLASH);
- }
-
- /* Add on the search pattern */
- _tcscat(nd->dd_name, SUFFIX);
-
- /* Initialize handle to -1 so that a premature closedir doesn't try
- * to call _findclose on it. */
- nd->dd_handle = -1;
-
- /* Initialize the status. */
- nd->dd_stat = 0;
-
- /* Initialize the dirent structure. ino and reclen are invalid under
- * Win32, and name simply points at the appropriate part of the
- * findfirst_t structure. */
- nd->dd_dir.d_ino = 0;
- nd->dd_dir.d_reclen = 0;
- nd->dd_dir.d_namlen = 0;
- memset(nd->dd_dir.d_name, 0, FILENAME_MAX);
-
- return nd;
+ struct __dir *data = NULL;
+ if (!dirp)
+ {
+ errno = EBADF;
+ return -1;
+ }
+ data = (struct __dir *) dirp;
+ CloseHandle((HANDLE) data->fd);
+ free(data->entries);
+ free(data);
+ return 0;
}
-//
-// readdir
-//
-// Return a pointer to a dirent structure filled with the information on the
-// next entry in the directory.
-//
-struct dirent *readdir(DIR *dirp)
+static void __seterrno(int value)
{
- errno = 0;
-
- /* Check for valid DIR struct. */
- if(!dirp)
- {
- errno = EFAULT;
- return (struct dirent *)0;
- }
-
- if (dirp->dd_stat < 0)
- {
- /* We have already returned all files in the directory
- * (or the structure has an invalid dd_stat). */
- return (struct dirent *)0;
- }
- else if (dirp->dd_stat == 0)
- {
- /* We haven't started the search yet. */
- /* Start the search */
- dirp->dd_handle = _tfindfirst(dirp->dd_name, &(dirp->dd_dta));
-
- if(dirp->dd_handle == -1)
- {
- /* Whoops! Seems there are no files in that
- * directory. */
- dirp->dd_stat = -1;
- }
- else
- {
- dirp->dd_stat = 1;
- }
- }
- else
- {
- /* Get the next search entry. */
- if(_tfindnext(dirp->dd_handle, &(dirp->dd_dta)))
- {
- /* We are off the end or otherwise error.
- _findnext sets errno to ENOENT if no more file
- Undo this. */
- DWORD winerr = GetLastError();
- if(winerr == ERROR_NO_MORE_FILES)
- errno = 0;
- _findclose(dirp->dd_handle);
- dirp->dd_handle = -1;
- dirp->dd_stat = -1;
- }
- else
- {
- /* Update the status to indicate the correct
- * number. */
- dirp->dd_stat++;
- }
- }
-
- if (dirp->dd_stat > 0)
- {
- /* Successfully got an entry. Everything about the file is
- * already appropriately filled in except the length of the
- * file name. */
- dirp->dd_dir.d_namlen = _tcslen(dirp->dd_dta.name);
- _tcscpy(dirp->dd_dir.d_name, dirp->dd_dta.name);
- return &dirp->dd_dir;
- }
-
- return (struct dirent *)0;
+#ifdef _MSC_VER
+ _set_errno(value);
+#else /* _MSC_VER */
+ errno = value;
+#endif /* _MSC_VER */
}
+static int __islink(const wchar_t *name, char *buffer)
+{
+ DWORD io_result = 0;
+ DWORD bytes_returned = 0;
+ HANDLE hFile = CreateFileW(
+ name, 0, 0, NULL, OPEN_EXISTING,
+ FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, 0);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ return 0;
+ }
-//
-// closedir
-//
-// Frees up resources allocated by opendir.
-//
-int closedir(DIR *dirp)
+ io_result = DeviceIoControl(hFile, FSCTL_GET_REPARSE_POINT, NULL, 0, buffer,
+ MAXIMUM_REPARSE_DATA_BUFFER_SIZE,
+ &bytes_returned, NULL);
+
+ CloseHandle(hFile);
+
+ if (io_result == 0)
+ {
+ return 0;
+ }
+
+ return ((REPARSE_GUID_DATA_BUFFER *) buffer)->ReparseTag ==
+ IO_REPARSE_TAG_SYMLINK;
+}
+
+#pragma pack(push, 1)
+
+typedef struct dirent_FILE_ID_128
+{
+ BYTE Identifier[16];
+} dirent_FILE_ID_128;
+
+typedef struct _dirent_FILE_ID_INFO
+{
+ ULONGLONG VolumeSerialNumber;
+ dirent_FILE_ID_128 FileId;
+} dirent_FILE_ID_INFO;
+
+#pragma pack(pop)
+
+typedef enum dirent_FILE_INFO_BY_HANDLE_CLASS
+{
+ dirent_FileIdInfo = 18
+} dirent_FILE_INFO_BY_HANDLE_CLASS;
+
+static __ino_t __inode(const wchar_t *name)
{
- int rc;
-
- errno = 0;
- rc = 0;
-
- if(!dirp)
- {
- errno = EFAULT;
- return -1;
- }
-
- if(dirp->dd_handle != -1)
- {
- rc = _findclose(dirp->dd_handle);
- }
-
- /* Delete the dir structure. */
- free(dirp);
-
- return rc;
+ __ino_t value = {0};
+ BOOL result;
+ dirent_FILE_ID_INFO fileid;
+ BY_HANDLE_FILE_INFORMATION info;
+ typedef BOOL(__stdcall * pfnGetFileInformationByHandleEx)(
+ HANDLE hFile, dirent_FILE_INFO_BY_HANDLE_CLASS FileInformationClass,
+ LPVOID lpFileInformation, DWORD dwBufferSize);
+
+ HANDLE hKernel32 = GetModuleHandleW(L"kernel32.dll");
+ if (!hKernel32)
+ {
+ return value;
+ }
+
+ pfnGetFileInformationByHandleEx fnGetFileInformationByHandleEx =
+ (pfnGetFileInformationByHandleEx) GetProcAddress(
+ hKernel32, "GetFileInformationByHandleEx");
+ if (!fnGetFileInformationByHandleEx)
+ {
+ return value;
+ }
+
+ HANDLE hFile = CreateFileW(name, GENERIC_READ, FILE_SHARE_READ, NULL,
+ OPEN_EXISTING, 0, 0);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ return value;
+ }
+
+ result = fnGetFileInformationByHandleEx(hFile, dirent_FileIdInfo, &fileid,
+ sizeof(fileid));
+ if (result)
+ {
+ value.serial = fileid.VolumeSerialNumber;
+ memcpy(value.fileid, fileid.FileId.Identifier, 16);
+ }
+ else
+ {
+ result = GetFileInformationByHandle(hFile, &info);
+ if (result)
+ {
+ value.serial = info.dwVolumeSerialNumber;
+ memcpy(value.fileid + 8, &info.nFileIndexHigh, 4);
+ memcpy(value.fileid + 12, &info.nFileIndexLow, 4);
+ }
+ }
+ CloseHandle(hFile);
+ return value;
}
-//
-// rewinddir
-//
-// Return to the beginning of the directory "stream". We simply call findclose
-// and then reset things like an opendir.
-//
-void rewinddir(DIR * dirp)
+static DIR *__internal_opendir(wchar_t *wname, int size)
{
- errno = 0;
-
- if(!dirp)
- {
- errno = EFAULT;
- return;
- }
-
- if(dirp->dd_handle != -1)
- {
- _findclose(dirp->dd_handle);
- }
-
- dirp->dd_handle = -1;
- dirp->dd_stat = 0;
+ struct __dir *data = NULL;
+ struct dirent *tmp_entries = NULL;
+ static char default_char = '?';
+ static wchar_t *prefix = L"\\\\?\\";
+ static wchar_t *suffix = L"\\*.*";
+ static int extra_prefix = 4; /* use prefix "\\?\" to handle long file names */
+ static int extra_suffix = 4; /* use suffix "\*.*" to find everything */
+ WIN32_FIND_DATAW w32fd = {0};
+ HANDLE hFindFile = INVALID_HANDLE_VALUE;
+ static int grow_factor = 2;
+ char *buffer = NULL;
+
+ BOOL relative = PathIsRelativeW(wname + extra_prefix);
+
+ memcpy(wname + size - 1, suffix, sizeof(wchar_t) * extra_suffix);
+ wname[size + extra_suffix - 1] = 0;
+
+ if (relative)
+ {
+ wname += extra_prefix;
+ size -= extra_prefix;
+ }
+ hFindFile = FindFirstFileW(wname, &w32fd);
+ if (INVALID_HANDLE_VALUE == hFindFile)
+ {
+ __seterrno(ENOENT);
+ return NULL;
+ }
+
+ data = (struct __dir *) malloc(sizeof(struct __dir));
+ if (!data)
+ {
+ goto out_of_memory;
+ }
+ wname[size - 1] = 0;
+ data->fd = (intptr_t) CreateFileW(wname, 0, 0, NULL, OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS, 0);
+ wname[size - 1] = L'\\';
+ data->count = 16;
+ data->index = 0;
+ data->entries = (struct dirent *) malloc(sizeof(struct dirent) * data->count);
+ if (!data->entries)
+ {
+ goto out_of_memory;
+ }
+ buffer = malloc(MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
+ if (!buffer)
+ {
+ goto out_of_memory;
+ }
+
+ do
+ {
+ WideCharToMultiByte(CP_UTF8, 0, w32fd.cFileName, -1,
+ data->entries[data->index].d_name, NAME_MAX,
+ &default_char, NULL);
+
+ memcpy(wname + size, w32fd.cFileName, sizeof(wchar_t) * NAME_MAX);
+
+ if (((w32fd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) ==
+ FILE_ATTRIBUTE_REPARSE_POINT)
+ && __islink(wname, buffer))
+ {
+ data->entries[data->index].d_type = DT_LNK;
+ }
+ else if ((w32fd.dwFileAttributes & FILE_ATTRIBUTE_DEVICE) ==
+ FILE_ATTRIBUTE_DEVICE)
+ {
+ data->entries[data->index].d_type = DT_CHR;
+ }
+ else if ((w32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ==
+ FILE_ATTRIBUTE_DIRECTORY)
+ {
+ data->entries[data->index].d_type = DT_DIR;
+ }
+ else
+ {
+ data->entries[data->index].d_type = DT_REG;
+ }
+
+ data->entries[data->index].d_ino = __inode(wname);
+ data->entries[data->index].d_reclen = sizeof(struct dirent);
+ data->entries[data->index].d_namelen =
+ (unsigned char) wcslen(w32fd.cFileName);
+ data->entries[data->index].d_off = 0;
+
+ if (++data->index == data->count)
+ {
+ tmp_entries = (struct dirent *) realloc(
+ data->entries,
+ sizeof(struct dirent) * data->count * grow_factor);
+ if (!tmp_entries)
+ {
+ goto out_of_memory;
+ }
+ data->entries = tmp_entries;
+ data->count *= grow_factor;
+ }
+ } while (FindNextFileW(hFindFile, &w32fd) != 0);
+
+ free(buffer);
+ FindClose(hFindFile);
+
+ data->count = data->index;
+ data->index = 0;
+ return (DIR *) data;
+
+out_of_memory:
+ if (data)
+ {
+ if (INVALID_HANDLE_VALUE != (HANDLE) data->fd)
+ {
+ CloseHandle((HANDLE) data->fd);
+ }
+ free(data->entries);
+ }
+ free(buffer);
+ free(data);
+ if (INVALID_HANDLE_VALUE != hFindFile)
+ {
+ FindClose(hFindFile);
+ }
+ __seterrno(ENOMEM);
+ return NULL;
+}
+
+static wchar_t *__get_buffer()
+{
+ wchar_t *name = malloc(sizeof(wchar_t) * (NTFS_MAX_PATH + NAME_MAX + 8));
+ if (name)
+ {
+ memcpy(name, L"\\\\?\\", sizeof(wchar_t) * 4);
+ }
+ return name;
}
-//
-// telldir
-//
-// Returns the "position" in the "directory stream" which can be used with
-// seekdir to go back to an old entry. We simply return the value in stat.
-//
-long telldir(DIR *dirp)
+DIR *opendir(const char *name)
{
- errno = 0;
-
- if(!dirp)
- {
- errno = EFAULT;
- return -1;
- }
- return dirp->dd_stat;
+ DIR *dirp = NULL;
+ wchar_t *wname = __get_buffer();
+ int size = 0;
+ if (!wname)
+ {
+ errno = ENOMEM;
+ return NULL;
+ }
+ size = MultiByteToWideChar(CP_UTF8, 0, name, -1, wname + 4, NTFS_MAX_PATH);
+ if (0 == size)
+ {
+ free(wname);
+ return NULL;
+ }
+ dirp = __internal_opendir(wname, size + 4);
+ free(wname);
+ return dirp;
}
-//
-// seekdir
-//
-// Seek to an entry previously returned by telldir. We rewind the directory
-// and call readdir repeatedly until either dd_stat is the position number
-// or -1 (off the end). This is not perfect, in that the directory may
-// have changed while we weren't looking. But that is probably the case with
-// any such system.
-//
-void seekdir(DIR *dirp, long lPos)
+DIR *_wopendir(const wchar_t *name)
{
- errno = 0;
-
- if(!dirp)
- {
- errno = EFAULT;
- return;
- }
-
- if(lPos < -1)
- {
- /* Seeking to an invalid position. */
- errno = EINVAL;
- return;
- }
- else if(lPos == -1)
- {
- /* Seek past end. */
- if(dirp->dd_handle != -1)
- {
- _findclose(dirp->dd_handle);
- }
- dirp->dd_handle = -1;
- dirp->dd_stat = -1;
- }
- else
- {
- /* Rewind and read forward to the appropriate index. */
- rewinddir(dirp);
-
- while((dirp->dd_stat < lPos) && readdir(dirp))
- ; /* do-nothing loop */
- }
+ DIR *dirp = NULL;
+ wchar_t *wname = __get_buffer();
+ int size = 0;
+ if (!wname)
+ {
+ errno = ENOMEM;
+ return NULL;
+ }
+ size = (int) wcslen(name);
+ if (size > NTFS_MAX_PATH)
+ {
+ free(wname);
+ return NULL;
+ }
+ memcpy(wname + 4, name, sizeof(wchar_t) * (size + 1));
+ dirp = __internal_opendir(wname, size + 5);
+ free(wname);
+ return dirp;
+}
+
+DIR *fdopendir(intptr_t fd)
+{
+ DIR *dirp = NULL;
+ wchar_t *wname = __get_buffer();
+ int size = 0;
+
+ if (!wname)
+ {
+ errno = ENOMEM;
+ return NULL;
+ }
+ size = GetFinalPathNameByHandleW((HANDLE) fd, wname + 4, NTFS_MAX_PATH,
+ FILE_NAME_NORMALIZED);
+ if (0 == size)
+ {
+ free(wname);
+ errno = ENOTDIR;
+ return NULL;
+ }
+ dirp = __internal_opendir(wname, size + 5);
+ free(wname);
+ return dirp;
}
-// EOF
+struct dirent *readdir(DIR *dirp)
+{
+ struct __dir *data = (struct __dir *) dirp;
+ if (!data)
+ {
+ errno = EBADF;
+ return NULL;
+ }
+ if (data->index < data->count)
+ {
+ return &data->entries[data->index++];
+ }
+ return NULL;
+}
+
+void seekdir(DIR *dirp, long int offset)
+{
+ if (dirp)
+ {
+ struct __dir *data = (struct __dir *) dirp;
+ data->index = (offset < data->count) ? offset : data->index;
+ }
+}
+
+void rewinddir(DIR *dirp)
+{
+ seekdir(dirp, 0);
+}
+
+long int telldir(DIR *dirp)
+{
+ if (!dirp)
+ {
+ errno = EBADF;
+ return -1;
+ }
+ return ((struct __dir *) dirp)->count;
+}
+
+intptr_t dirfd(DIR *dirp)
+{
+ if (!dirp)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ return ((struct __dir *) dirp)->fd;
+}
+#endif /* _WIN32 */
diff --git a/win32/win_opendir.h b/win32/win_opendir.h
index c1844e115e..94c9d2c848 100644
--- a/win32/win_opendir.h
+++ b/win32/win_opendir.h
@@ -1,73 +1,130 @@
-//
-// 03/10/2006 James Haley
-//
-// For this module only:
-// This code is public domain. No change sufficient enough to constitute a
-// significant or original work has been made, and thus it remains as such.
-//
-//
-// DESCRIPTION:
-//
-// Implementation of POSIX opendir for Visual C++.
-// Derived from the MinGW C Library Extensions Source (released to the
-// public domain).
-//
-
-#ifndef I_OPNDIR_H__
-#define I_OPNDIR_H__
-
-#include
-
-#ifndef FILENAME_MAX
-#define FILENAME_MAX 260
-#endif
+/*
+MIT License
+Copyright (c) 2019 win32ports
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#ifdef _WIN32
+
+#ifndef WIN_OPENDIR_H
+#define WIN_OPENDIR_H
+
+#include
+
+#ifndef NAME_MAX
+#define NAME_MAX 260
+#endif /* NAME_MAX */
+
+#ifndef DT_UNKNOWN
+#define DT_UNKNOWN 0
+#endif /* DT_UNKNOWN */
+
+#ifndef DT_FIFO
+#define DT_FIFO 1
+#endif /* DT_FIFO */
+
+#ifndef DT_CHR
+#define DT_CHR 2
+#endif /* DT_CHR */
+
+#ifndef DT_DIR
+#define DT_DIR 4
+#endif /* DT_DIR */
+
+#ifndef DT_BLK
+#define DT_BLK 6
+#endif /* DT_BLK */
+
+#ifndef DT_REG
+#define DT_REG 8
+#endif /* DT_REF */
+
+#ifndef DT_LNK
+#define DT_LNK 10
+#endif /* DT_LNK */
+
+#ifndef DT_SOCK
+#define DT_SOCK 12
+#endif /* DT_SOCK */
+
+#ifndef DT_WHT
+#define DT_WHT 14
+#endif /* DT_WHT */
+
+#ifndef _DIRENT_HAVE_D_NAMLEN
+#define _DIRENT_HAVE_D_NAMLEN 1
+#endif /* _DIRENT_HAVE_D_NAMLEN */
+
+#ifndef _DIRENT_HAVE_D_RECLEN
+#define _DIRENT_HAVE_D_RECLEN 1
+#endif /* _DIRENT_HAVE_D_RECLEN */
+
+#ifndef _DIRENT_HAVE_D_OFF
+#define _DIRENT_HAVE_D_OFF 1
+#endif /* _DIRENT_HAVE_D_OFF */
+
+#ifndef _DIRENT_HAVE_D_TYPE
+#define _DIRENT_HAVE_D_TYPE 1
+#endif /* _DIRENT_HAVE_D_TYPE */
+
+typedef void *DIR;
+
+typedef struct ino_t
+{
+ unsigned long long serial;
+ unsigned char fileid[16];
+} __ino_t;
struct dirent
{
- long d_ino; /* Always zero. */
- unsigned short d_reclen; /* Always zero. */
- unsigned short d_namlen; /* Length of name in d_name. */
- char d_name[FILENAME_MAX]; /* File name. */
+ __ino_t d_ino;
+ off_t d_off;
+ unsigned short d_reclen;
+ unsigned char d_namelen;
+ unsigned char d_type;
+ char d_name[NAME_MAX];
};
-/*
- * This is an internal data structure. Good programmers will not use it
- * except as an argument to one of the functions below.
- * dd_stat field is now int (was short in older versions).
- */
-typedef struct
+struct __dir
{
- /* disk transfer area for this dir */
- struct _finddata_t dd_dta;
+ struct dirent *entries;
+ intptr_t fd;
+ long int count;
+ long int index;
+};
+
+int closedir(DIR *dirp);
+
+DIR *opendir(const char *name);
+
+DIR *_wopendir(const wchar_t *name);
- /* dirent struct to return from dir (NOTE: this makes this thread
- * safe as long as only one thread uses a particular DIR struct at
- * a time) */
- struct dirent dd_dir;
+DIR *fdopendir(intptr_t fd);
- /* _findnext handle */
- intptr_t dd_handle;
+struct dirent *readdir(DIR *dirp);
- /*
- * Status of search:
- * 0 = not started yet (next entry to read is first entry)
- * -1 = off the end
- * positive = 0 based index of next entry
- */
- int dd_stat;
+void seekdir(DIR *dirp, long int offset);
- /* given path for dir with search pattern (struct is extended) */
- char dd_name[1];
-} DIR;
+void rewinddir(DIR *dirp);
-DIR *opendir(const char *);
-struct dirent *readdir(DIR *);
-int closedir(DIR *);
-void rewinddir(DIR *);
-long telldir(DIR *);
-void seekdir(DIR *, long);
+long int telldir(DIR *dirp);
-#endif
+intptr_t dirfd(DIR *dirp);
-// EOF
+#endif /* WIN_OPENDIR_H */
+#endif /* _WIN32 */