From e8843dba3eb1c7a67f6ff7b920046ae36a12acd0 Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Mon, 16 May 2022 20:23:39 +0100 Subject: Make the demo directory check more robust This is how it should've been to begin with, but I was lazy. --- src/demorec.c | 28 ++++++++++++++++++++++++---- src/os-win32.h | 3 +++ src/os.h | 1 + 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/demorec.c b/src/demorec.c index 2108436..c8871bd 100644 --- a/src/demorec.c +++ b/src/demorec.c @@ -88,7 +88,8 @@ static void hook_record_cb(const struct con_cmdargs *args) { bool was = *recording; if (!was && args->argc == 2 || args->argc == 3) { // safety check: make sure a directory exists, otherwise recording - // silently fails + // silently fails. this is necessarily TOCTOU, but in practice it's + // way better than not doing it - just to have a sanity check. const char *arg = args->argv[1]; const char *lastslash = 0; for (const char *p = arg; *p; ++p) { @@ -111,9 +112,28 @@ static void hook_record_cb(const struct con_cmdargs *args) { *q = (uchar)*p; } q[argdirlen] = OS_LIT('\0'); - if (os_access(dir, X_OK) == -1) { - con_warn("ERROR: can't record demo: subdirectory %.*s " - "doesn't exist\n", argdirlen, arg); + // this is pretty ugly. the error cases would be way tidier if + // we could use open(O_DIRECTORY), but that's not a thing on + // windows, of course. + struct os_stat s; + if (os_stat(dir, &s) == -1) { + con_warn("ERROR: can't record demo: "); + if (errno == ENOENT) { + con_warn("subdirectory %.*s doesn't exist\n", + argdirlen, arg); + } + else { + con_warn("%s\n", strerror(errno)); // guess this'll do. + } + return; + } + if (!S_ISDIR(s.st_mode)) { + // duping this warning call to avoid duping the string data, + // very stupid, oh well. if/when we have New And Improved + // Logging this can be tidied up... + con_warn("ERROR: can't record demo: "); + con_warn("the path %.*s is not a directory\n", + argdirlen, arg); return; } } diff --git a/src/os-win32.h b/src/os-win32.h index 8aeb93a..12720a9 100644 --- a/src/os-win32.h +++ b/src/os-win32.h @@ -109,6 +109,9 @@ static inline void os_randombytes(void *buf, int sz) { #define W_OK 2 #define X_OK R_OK // there's no actual X bit, just pretend +// windows doesn't define this for some reason!? note: add others as needed... +#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) + // just dump this boilerplate here as well, I spose #define OS_WINDOWS_ERROR(arrayname) \ FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(), \ diff --git a/src/os.h b/src/os.h index c00eaf3..3d3ab00 100644 --- a/src/os.h +++ b/src/os.h @@ -46,6 +46,7 @@ #include #include #include +#include #include #endif -- cgit v1.2.3