diff options
Diffstat (limited to 'osdep/io.c')
-rw-r--r-- | osdep/io.c | 141 |
1 files changed, 65 insertions, 76 deletions
@@ -189,7 +189,7 @@ static bool get_file_ids_win8(HANDLE h, dev_t *dev, ino_t *ino) // SDK, but we can ignore that by just memcpying it. This will also // truncate the file ID on 32-bit Windows, which doesn't support __int128. // 128-bit file IDs are only used for ReFS, so that should be okay. - assert(sizeof(*ino) <= sizeof(ii.FileId)); + static_assert(sizeof(*ino) <= sizeof(ii.FileId), ""); memcpy(ino, &ii.FileId, sizeof(*ino)); return true; } @@ -298,62 +298,53 @@ int mp_fstat(int fd, struct mp_stat *buf) return hstat(h, buf); } -#if HAVE_UWP -static int mp_vfprintf(FILE *stream, const char *format, va_list args) +static inline HANDLE get_handle(FILE *stream) { - return vfprintf(stream, format, args); -} -#else -static int mp_check_console(HANDLE wstream) -{ - if (wstream != INVALID_HANDLE_VALUE) { - unsigned int filetype = GetFileType(wstream); + HANDLE wstream = INVALID_HANDLE_VALUE; - if (!((filetype == FILE_TYPE_UNKNOWN) && - (GetLastError() != ERROR_SUCCESS))) - { - filetype &= ~(FILE_TYPE_REMOTE); + if (stream == stdout || stream == stderr) { + wstream = GetStdHandle(stream == stdout ? + STD_OUTPUT_HANDLE : STD_ERROR_HANDLE); + } + return wstream; +} - if (filetype == FILE_TYPE_CHAR) { - DWORD ConsoleMode; - int ret = GetConsoleMode(wstream, &ConsoleMode); +size_t mp_fwrite(const void *restrict buffer, size_t size, size_t count, + FILE *restrict stream) +{ + if (!size || !count) + return 0; - if (!(!ret && (GetLastError() == ERROR_INVALID_HANDLE))) { - // This seems to be a console - return 1; - } - } + HANDLE wstream = get_handle(stream); + if (mp_check_console(wstream)) { + unsigned char *start = (unsigned char *)buffer; + size_t c = 0; + for (; c < count; ++c) { + if (mp_console_write(wstream, (bstr){start, size}) <= 0) + break; + start += size; } + return c; } - return 0; +#undef fwrite + return fwrite(buffer, size, count, stream); } +#if HAVE_UWP static int mp_vfprintf(FILE *stream, const char *format, va_list args) { - int done = 0; - - HANDLE wstream = INVALID_HANDLE_VALUE; - - if (stream == stdout || stream == stderr) { - wstream = GetStdHandle(stream == stdout ? - STD_OUTPUT_HANDLE : STD_ERROR_HANDLE); - } - - if (mp_check_console(wstream)) { - size_t len = vsnprintf(NULL, 0, format, args) + 1; - char *buf = talloc_array(NULL, char, len); + return vfprintf(stream, format, args); +} +#else - if (buf) { - done = vsnprintf(buf, len, format, args); - mp_write_console_ansi(wstream, buf); - } - talloc_free(buf); - } else { - done = vfprintf(stream, format, args); - } +static int mp_vfprintf(FILE *stream, const char *format, va_list args) +{ + HANDLE wstream = get_handle(stream); + if (mp_check_console(wstream)) + return mp_console_vfprintf(wstream, format, args); - return done; + return vfprintf(stream, format, args); } #endif @@ -558,7 +549,9 @@ FILE *mp_fopen(const char *filename, const char *mode) // Thus we need MP_PATH_MAX as the UTF-8/char version of PATH_MAX. // Also make sure there's free space for the terminating \0. // (For codepoints encoded as UTF-16 surrogate pairs, UTF-8 has the same length.) -#define MP_PATH_MAX (FILENAME_MAX * 3 + 1) +// Lastly, note that neither _wdirent nor WIN32_FIND_DATA can store filenames +// longer than this, so long-path support for readdir() is impossible. +#define MP_FILENAME_MAX (FILENAME_MAX * 3 + 1) struct mp_dir { DIR crap; // must be first member @@ -568,9 +561,9 @@ struct mp_dir { // dirent has space only for FILENAME_MAX bytes. _wdirent has space for // FILENAME_MAX wchar_t, which might end up bigger as UTF-8 in some // cases. Guarantee we can always hold _wdirent.d_name converted to - // UTF-8 (see MP_PATH_MAX). + // UTF-8 (see above). // This works because dirent.d_name is the last member of dirent. - char space[MP_PATH_MAX]; + char space[MP_FILENAME_MAX]; }; }; @@ -620,6 +613,14 @@ int mp_mkdir(const char *path, int mode) return res; } +int mp_unlink(const char *path) +{ + wchar_t *wpath = mp_from_utf8(NULL, path); + int res = _wunlink(wpath); + talloc_free(wpath); + return res; +} + char *mp_win32_getcwd(char *buf, size_t size) { if (size >= SIZE_MAX / 3 - 1) { @@ -736,9 +737,23 @@ static void mp_dl_init(void) void *mp_dlopen(const char *filename, int flag) { - wchar_t *wfilename = mp_from_utf8(NULL, filename); - HMODULE lib = LoadLibraryW(wfilename); - talloc_free(wfilename); + HMODULE lib = NULL; + void *ta_ctx = talloc_new(NULL); + wchar_t *wfilename = mp_from_utf8(ta_ctx, filename); + + DWORD len = GetFullPathNameW(wfilename, 0, NULL, NULL); + if (!len) + goto err; + + wchar_t *path = talloc_array(ta_ctx, wchar_t, len); + len = GetFullPathNameW(wfilename, len, path, NULL); + if (!len) + goto err; + + lib = LoadLibraryW(path); + +err: + talloc_free(ta_ctx); mp_dl_result.errcode = GetLastError(); return (void *)lib; } @@ -876,29 +891,3 @@ void freelocale(locale_t locobj) } #endif // __MINGW32__ - -int mp_mkostemps(char *template, int suffixlen, int flags) -{ - size_t len = strlen(template); - char *t = len >= 6 + suffixlen ? &template[len - (6 + suffixlen)] : NULL; - if (!t || strncmp(t, "XXXXXX", 6) != 0) { - errno = EINVAL; - return -1; - } - - for (size_t fuckshit = 0; fuckshit < UINT32_MAX; fuckshit++) { - // Using a random value may make it require fewer iterations (even if - // not truly random; just a counter would be sufficient). - size_t fuckmess = mp_rand_next(); - char crap[7] = ""; - snprintf(crap, sizeof(crap), "%06zx", fuckmess); - memcpy(t, crap, 6); - - int res = open(template, O_RDWR | O_CREAT | O_EXCL | flags, 0600); - if (res >= 0 || errno != EEXIST) - return res; - } - - errno = EEXIST; - return -1; -} |