From bec8e6d8924179fac3cee47e2b75af45b3ead521 Mon Sep 17 00:00:00 2001 From: cancername <93018402+sus-impost0r@users.noreply.github.com> Date: Mon, 31 Jul 2023 21:40:31 +0200 Subject: [PATCH] Fix a bug on FreeBSD caused by assuming that short reads are errors Signed-off-by: notcancername <119271574+notcancername@users.noreply.github.com> --- fs.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++-------- todo | 2 +- 2 files changed, 72 insertions(+), 12 deletions(-) diff --git a/fs.c b/fs.c index e7a001bf..af62b898 100644 --- a/fs.c +++ b/fs.c @@ -109,6 +109,66 @@ static filedesc_t FILEDESC_DUP(const char *filename, filedesc_t fd) { } #endif + +/* This code seems to have originally been written with the assumption that + * read(..., n) returns n on success. This is not the case (refer to + * ). + * Ditto for write. + */ + +/* +==================== +ReadAll + +Read exactly length bytes from fd into buf. If end of file is reached, +the number of bytes read is returned. If an error occurred, that error +is returned. Note that if an error is returned, any previously read +data is lost. +==================== +*/ +static fs_offset_t ReadAll(const filedesc_t fd, void *const buf, const size_t length) +{ + char *const p = (char *)buf; + size_t cursor = 0; + do + { + const fs_offset_t result = FILEDESC_READ(fd, p + cursor, length - cursor); + if (result < 0) // Error + return result; + if (result == 0) // EOF + break; + cursor += result; + } while (cursor < length); + return cursor; +} + +/* +==================== +WriteAll + +Write exactly length bytes to fd from buf. +If an error occurred, that error is returned. +==================== +*/ +static fs_offset_t WriteAll(const filedesc_t fd, const void *const buf, const size_t length) +{ + const char *const p = (const char *)buf; + size_t cursor = 0; + do + { + const fs_offset_t result = FILEDESC_WRITE(fd, p + cursor, length - cursor); + if (result < 0) // Error + return result; + cursor += result; + } while (cursor < length); + return cursor; +} + +#undef FILEDESC_READ +#define FILEDESC_READ ReadAll +#undef FILEDESC_WRITE +#define FILEDESC_WRITE WriteAll + /** \page fs File System All of Quake's data access is through a hierchal file system, but the contents @@ -455,7 +515,7 @@ static const char* shfolderdllnames [] = }; static dllhandle_t shfolder_dll = NULL; -const GUID qFOLDERID_SavedGames = {0x4C5C32FF, 0xBB9D, 0x43b0, {0xB5, 0xB4, 0x2D, 0x72, 0xE5, 0x4E, 0xAA, 0xA4}}; +const GUID qFOLDERID_SavedGames = {0x4C5C32FF, 0xBB9D, 0x43b0, {0xB5, 0xB4, 0x2D, 0x72, 0xE5, 0x4E, 0xAA, 0xA4}}; #define qREFKNOWNFOLDERID const GUID * #define qKF_FLAG_CREATE 0x8000 #define qKF_FLAG_NO_ALIAS 0x1000 @@ -1762,7 +1822,7 @@ const char *FS_CheckGameDir(const char *gamedir) ret = FS_SysCheckGameDir(va(vabuf, sizeof(vabuf), "%s%s/", fs_basedir, gamedir), buf, sizeof(buf)); if(ret) return ret; - + return fs_checkgamedir_missing; } @@ -1795,7 +1855,7 @@ static void FS_ListGameDirs(void) continue; if(!*info) continue; - stringlistappend(&list2, list.strings[i]); + stringlistappend(&list2, list.strings[i]); } stringlistfreecontents(&list); @@ -2583,7 +2643,7 @@ int FS_CheckNastyPath (const char *path, qbool isgamedir) ==================== FS_SanitizePath -Sanitize path (replace non-portable characters +Sanitize path (replace non-portable characters with portable ones in-place, etc) ==================== */ @@ -2740,7 +2800,7 @@ static qfile_t *FS_OpenReadFile (const char *filename, qbool quiet, qbool nonblo if(count < 0) return NULL; linkbuf[count] = 0; - + // Now combine the paths... mergeslash = strrchr(filename, '/'); mergestart = linkbuf; @@ -3974,7 +4034,7 @@ void FS_Which_f(cmd_state_t *cmd) { Con_Printf("usage:\n%s \n", Cmd_Argv(cmd, 0)); return; - } + } filename = Cmd_Argv(cmd, 1); sp = FS_FindFile(filename, &index, true); if (!sp) { @@ -4127,7 +4187,7 @@ unsigned char *FS_Deflate(const unsigned char *data, size_t size, size_t *deflat Mem_Free(tmp); return NULL; } - + if(qz_deflateEnd(&strm) != Z_OK) { Con_Printf("FS_Deflate: deflateEnd failed\n"); @@ -4154,7 +4214,7 @@ unsigned char *FS_Deflate(const unsigned char *data, size_t size, size_t *deflat memcpy(out, tmp, strm.total_out); Mem_Free(tmp); - + return out; } @@ -4221,7 +4281,7 @@ unsigned char *FS_Inflate(const unsigned char *data, size_t size, size_t *inflat case Z_STREAM_END: case Z_OK: break; - + case Z_STREAM_ERROR: Con_Print("FS_Inflate: stream error!\n"); break; @@ -4237,7 +4297,7 @@ unsigned char *FS_Inflate(const unsigned char *data, size_t size, size_t *inflat default: Con_Print("FS_Inflate: unknown error!\n"); break; - + } if(ret != Z_OK && ret != Z_STREAM_END) { @@ -4265,6 +4325,6 @@ unsigned char *FS_Inflate(const unsigned char *data, size_t size, size_t *inflat Mem_Free(outbuf.data); *inflated_size = (size_t)outbuf.cursize; - + return out; } diff --git a/todo b/todo index 28e8cb6c..19c25c34 100644 --- a/todo +++ b/todo @@ -265,7 +265,6 @@ 0 optimize darkplaces renderer: get rid of attenuation texture on lights because math is faster, add fastpath for no normalmap (Lava_Croft) 1 bug darkplaces WGL client: figure out why for some people GDI input has stuttering problems with gl_finish 0 mode (Kinn, Urre, romi, Spike, Black) 1 bug darkplaces WGL/GLX/SDL client bug: if sound is unavailable (causing a freeze waiting for it to become available), the config is reset (SavageX) -1 bug darkplaces bsd filesystem: read() is failing (not returning the requested amount) on freebsd when reading files, whether actual files or in a pk3 - somehow it is still able to read the pk3 zip directory though (suminigashi, Elric) 1 bug darkplaces collisions: curve collisions sometimes catch on the lip of the edge, pushing into the curved back wall around certain jumppads in Nexuiz for example consistently gets stuck just below the ledge (HReaper) 1 bug darkplaces command: "rate", "playermodel", "playerskin", "pmodel" commands can spam server console with usage statements (Spike) 1 bug darkplaces console: when logging using log_file and log_sync 0, setting log_file back to "" does not close the file until another message is posted? @@ -1356,6 +1355,7 @@ d revelation: fix lingering glow on lightning deaths (romi) d revelation: reduce damage from weapons (romi) d sv_user.qc: figure out why looking up/down slows movement and fix it (Vermeulen) d zmodel: fix scale and origin commands (Vermeulen) +-d bug darkplaces bsd filesystem: read() is failing (not returning the requested amount) on freebsd when reading files, whether actual files or in a pk3 - somehow it is still able to read the pk3 zip directory though (suminigashi, Elric) f LordHavoc: examine .mb (Maya Binary) file from Electro and learn its format (Electro) f bug darkplaces capturevideo: cl_capturevideo 1 with sound off is not locking the framerate of a server (Vermeulen) f bug darkplaces client: decals are not sticking to submodels -- 2.39.2