From 9d25ba7ac51ec247df2c58e76fc6ba9501326dc0 Mon Sep 17 00:00:00 2001 From: Tunip3 Date: Sat, 25 Sep 2021 17:44:25 +0100 Subject: [PATCH 1/2] reimplent vfs files without using storagefile --- .../vfs/vfs_implementation_uwp.cpp | 961 ++++++++++++------ 1 file changed, 654 insertions(+), 307 deletions(-) diff --git a/libretro-common/vfs/vfs_implementation_uwp.cpp b/libretro-common/vfs/vfs_implementation_uwp.cpp index c96972e134..3fbf029103 100644 --- a/libretro-common/vfs/vfs_implementation_uwp.cpp +++ b/libretro-common/vfs/vfs_implementation_uwp.cpp @@ -33,6 +33,8 @@ #include #include #include +#include +#include using namespace Windows::Foundation; using namespace Windows::Foundation::Collections; @@ -318,365 +320,456 @@ HRESULT GetHandleFromStorageFile(Windows::Storage::StorageFile^ file, HANDLE* ha return E_FAIL; } +//#ifdef VFS_FRONTEND +//struct retro_vfs_file_handle +//#else +//struct libretro_vfs_implementation_file +//#endif +//{ +// IRandomAccessStream^ fp; +// IBuffer^ bufferp; +// HANDLE file_handle; +// char* buffer; +// char* orig_path; +// size_t buffer_size; +// int buffer_left; +// size_t buffer_fill; +//}; + #ifdef VFS_FRONTEND struct retro_vfs_file_handle #else struct libretro_vfs_implementation_file #endif { - IRandomAccessStream^ fp; - IBuffer^ bufferp; - HANDLE file_handle; - char* buffer; - char* orig_path; - size_t buffer_size; - int buffer_left; - size_t buffer_fill; + int64_t size; + uint64_t mappos; + uint64_t mapsize; + FILE* fp; + HANDLE fh; + char* buf; + char* orig_path; + uint8_t* mapped; + int fd; + unsigned hints; + enum vfs_scheme scheme; }; -libretro_vfs_implementation_file *retro_vfs_file_open_impl( - const char *path, unsigned mode, unsigned hints) +#define RFILE_HINT_UNBUFFERED (1 << 8) + + + +//int retro_vfs_file_close_impl(libretro_vfs_implementation_file *stream) +//{ +// if (!stream || (!stream->fp && stream->file_handle == INVALID_HANDLE_VALUE)) +// return -1; +// +// if (stream->file_handle != INVALID_HANDLE_VALUE) +// CloseHandle(stream->file_handle); +// else +// { +// /* Apparently, this is how you close a file in WinRT */ +// /* Yes, really */ +// stream->fp = nullptr; +// free(stream->buffer); +// } +// +// return 0; +//} + +int retro_vfs_file_close_impl(libretro_vfs_implementation_file* stream) { - char dirpath[PATH_MAX_LENGTH]; - char filename[PATH_MAX_LENGTH]; - wchar_t *path_wide; - wchar_t *dirpath_wide; - wchar_t *filename_wide; - Platform::String^ path_str; - Platform::String^ filename_str; - Platform::String^ dirpath_str; - HANDLE file_handle = INVALID_HANDLE_VALUE; - DWORD desireAccess; - DWORD creationDisposition; + if (!stream) + return -1; - if (!path || !*path) - return NULL; + /*if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) + { + if (stream->fp) + fclose(stream->fp); + }*/ - /* Something tried to access files from current directory. - * This is not allowed on UWP. */ - if (!path_is_absolute(path)) - return NULL; + if (stream->fp) + fclose(stream->fp); - /* Trying to open a directory as file?! */ - if (PATH_CHAR_IS_SLASH(path[strlen(path) - 1])) - return NULL; + /*if (stream->fd > 0) + { + fclose(stream->fd); + }*/ + if (stream->buf != NULL) + { + free(stream->buf); + stream->buf = NULL; + } + if (stream->orig_path) + free(stream->orig_path); - dirpath[0] = filename[0] = '\0'; + free(stream); - path_wide = utf8_to_utf16_string_alloc(path); - windowsize_path(path_wide); - std::wstring temp_path = path_wide; - while (true) { - size_t p = temp_path.find(L"\\\\"); - if (p == std::wstring::npos) break; - temp_path.replace(p, 2, L"\\"); - } - path_wide = _wcsdup(temp_path.c_str()); - path_str = ref new Platform::String(path_wide); - free(path_wide); - - fill_pathname_basedir(dirpath, path, sizeof(dirpath)); - dirpath_wide = utf8_to_utf16_string_alloc(dirpath); - windowsize_path(dirpath_wide); - dirpath_str = ref new Platform::String(dirpath_wide); - free(dirpath_wide); - - fill_pathname_base(filename, path, sizeof(filename)); - filename_wide = utf8_to_utf16_string_alloc(filename); - filename_str = ref new Platform::String(filename_wide); - free(filename_wide); - - retro_assert(!dirpath_str->IsEmpty() && !filename_str->IsEmpty()); - - /* Try Win32 first, this should work in AppData */ - switch (mode) - { - case RETRO_VFS_FILE_ACCESS_READ_WRITE: - desireAccess = GENERIC_READ | GENERIC_WRITE; - break; - case RETRO_VFS_FILE_ACCESS_WRITE: - desireAccess = GENERIC_WRITE; - break; - case RETRO_VFS_FILE_ACCESS_READ: - desireAccess = GENERIC_READ; - break; - } - if (mode == RETRO_VFS_FILE_ACCESS_READ) - { - creationDisposition = OPEN_EXISTING; - } - else - { - creationDisposition = (mode & RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING) != 0 ? - OPEN_ALWAYS : CREATE_ALWAYS; - } - path_str = "\\\\?\\" + path_str; - file_handle = CreateFile2FromAppW(path_str->Data(), desireAccess, FILE_SHARE_READ, creationDisposition, NULL); - - if (file_handle != INVALID_HANDLE_VALUE) - { - libretro_vfs_implementation_file* stream = (libretro_vfs_implementation_file*)calloc(1, sizeof(*stream)); - if (!stream) - return (libretro_vfs_implementation_file*)NULL; - - stream->orig_path = strdup(path); - stream->fp = nullptr; - stream->file_handle = file_handle; - stream->buffer_left = 0; - stream->buffer_fill = 0; - return stream; - } - return NULL; + return 0; } -int retro_vfs_file_close_impl(libretro_vfs_implementation_file *stream) +//int retro_vfs_file_error_impl(libretro_vfs_implementation_file *stream) +//{ +// return false; /* TODO */ +//} + +int retro_vfs_file_error_impl(libretro_vfs_implementation_file* stream) { - if (!stream || (!stream->fp && stream->file_handle == INVALID_HANDLE_VALUE)) - return -1; - - if (stream->file_handle != INVALID_HANDLE_VALUE) - CloseHandle(stream->file_handle); - else - { - /* Apparently, this is how you close a file in WinRT */ - /* Yes, really */ - stream->fp = nullptr; - free(stream->buffer); - } - - return 0; + return ferror(stream->fp); } -int retro_vfs_file_error_impl(libretro_vfs_implementation_file *stream) +//int64_t retro_vfs_file_size_impl(libretro_vfs_implementation_file *stream) +//{ +// if (!stream || (!stream->fp && stream->file_handle == INVALID_HANDLE_VALUE)) +// return 0; +// +// if (stream->file_handle != INVALID_HANDLE_VALUE) +// { +// LARGE_INTEGER sz; +// if (GetFileSizeEx(stream->file_handle, &sz)) +// return sz.QuadPart; +// return 0; +// } +// +// return stream->fp->Size; +//} + +int64_t retro_vfs_file_size_impl(libretro_vfs_implementation_file* stream) { - return false; /* TODO */ + if (stream) + return stream->size; + return 0; } -int64_t retro_vfs_file_size_impl(libretro_vfs_implementation_file *stream) +//int64_t retro_vfs_file_truncate_impl(libretro_vfs_implementation_file *stream, int64_t length) +//{ +// if (!stream || (!stream->fp && stream->file_handle == INVALID_HANDLE_VALUE)) +// return -1; +// +// if (stream->file_handle != INVALID_HANDLE_VALUE) +// { +// int64_t p = retro_vfs_file_tell_impl(stream); +// retro_vfs_file_seek_impl(stream, length, RETRO_VFS_SEEK_POSITION_START); +// SetEndOfFile(stream->file_handle); +// +// if (p < length) +// retro_vfs_file_seek_impl(stream, p, RETRO_VFS_SEEK_POSITION_START); +// } +// else +// stream->fp->Size = length; +// +// return 0; +//} + +int64_t retro_vfs_file_truncate_impl(libretro_vfs_implementation_file* stream, int64_t length) { - if (!stream || (!stream->fp && stream->file_handle == INVALID_HANDLE_VALUE)) - return 0; + if (!stream) + return -1; - if (stream->file_handle != INVALID_HANDLE_VALUE) - { - LARGE_INTEGER sz; - if (GetFileSizeEx(stream->file_handle, &sz)) - return sz.QuadPart; - return 0; - } + if (_chsize(_fileno(stream->fp), length) != 0) + return -1; - return stream->fp->Size; + return 0; } -int64_t retro_vfs_file_truncate_impl(libretro_vfs_implementation_file *stream, int64_t length) +//int64_t retro_vfs_file_tell_impl(libretro_vfs_implementation_file *stream) +//{ +// LARGE_INTEGER _offset; +// LARGE_INTEGER out; +// _offset.QuadPart = 0; +// +// if (!stream || (!stream->fp && stream->file_handle == INVALID_HANDLE_VALUE)) +// return -1; +// +// if (stream->file_handle != INVALID_HANDLE_VALUE) +// { +// SetFilePointerEx(stream->file_handle, _offset, &out, FILE_CURRENT); +// return out.QuadPart; +// } +// +// return stream->fp->Position - stream->buffer_left; +//} + + +int64_t retro_vfs_file_tell_impl(libretro_vfs_implementation_file* stream) { - if (!stream || (!stream->fp && stream->file_handle == INVALID_HANDLE_VALUE)) - return -1; + if (!stream) + return -1; - if (stream->file_handle != INVALID_HANDLE_VALUE) - { - int64_t p = retro_vfs_file_tell_impl(stream); - retro_vfs_file_seek_impl(stream, length, RETRO_VFS_SEEK_POSITION_START); - SetEndOfFile(stream->file_handle); + if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) + { + return ftell(stream->fp); + } + if (lseek(stream->fd, 0, SEEK_CUR) < 0) + return -1; - if (p < length) - retro_vfs_file_seek_impl(stream, p, RETRO_VFS_SEEK_POSITION_START); - } - else - stream->fp->Size = length; - - return 0; + return 0; } -int64_t retro_vfs_file_tell_impl(libretro_vfs_implementation_file *stream) +//int64_t retro_vfs_file_seek_impl( +// libretro_vfs_implementation_file *stream, +// int64_t offset, int seek_position) +//{ +// LARGE_INTEGER _offset; +// _offset.QuadPart = offset; +// +// if (!stream || (!stream->fp && stream->file_handle == INVALID_HANDLE_VALUE)) +// return -1; +// +// switch (seek_position) +// { +// case RETRO_VFS_SEEK_POSITION_START: +// if (stream->file_handle != INVALID_HANDLE_VALUE) +// SetFilePointerEx(stream->file_handle, _offset, NULL, FILE_BEGIN); +// else +// stream->fp->Seek(offset); +// break; +// +// case RETRO_VFS_SEEK_POSITION_CURRENT: +// if (stream->file_handle != INVALID_HANDLE_VALUE) +// SetFilePointerEx(stream->file_handle, _offset, NULL, FILE_CURRENT); +// else +// stream->fp->Seek(retro_vfs_file_tell_impl(stream) + offset); +// break; +// +// case RETRO_VFS_SEEK_POSITION_END: +// if (stream->file_handle != INVALID_HANDLE_VALUE) +// SetFilePointerEx(stream->file_handle, _offset, NULL, FILE_END); +// else +// stream->fp->Seek(stream->fp->Size - offset); +// break; +// } +// +// /* For simplicity always flush the buffer on seek */ +// stream->buffer_left = 0; +// +// return 0; +//} + +int64_t retro_vfs_file_seek_internal( + libretro_vfs_implementation_file* stream, + int64_t offset, int whence) { - LARGE_INTEGER _offset; - LARGE_INTEGER out; - _offset.QuadPart = 0; + if (!stream) + return -1; - if (!stream || (!stream->fp && stream->file_handle == INVALID_HANDLE_VALUE)) - return -1; + if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) + { + return _fseeki64(stream->fp, offset, whence); + } - if (stream->file_handle != INVALID_HANDLE_VALUE) - { - SetFilePointerEx(stream->file_handle, _offset, &out, FILE_CURRENT); - return out.QuadPart; - } - return stream->fp->Position - stream->buffer_left; + if (lseek(stream->fd, (off_t)offset, whence) < 0) + return -1; + + return 0; } -int64_t retro_vfs_file_seek_impl( - libretro_vfs_implementation_file *stream, - int64_t offset, int seek_position) +int64_t retro_vfs_file_seek_impl(libretro_vfs_implementation_file* stream, + int64_t offset, int seek_position) { - LARGE_INTEGER _offset; - _offset.QuadPart = offset; + int whence = -1; + switch (seek_position) + { + case RETRO_VFS_SEEK_POSITION_START: + whence = SEEK_SET; + break; + case RETRO_VFS_SEEK_POSITION_CURRENT: + whence = SEEK_CUR; + break; + case RETRO_VFS_SEEK_POSITION_END: + whence = SEEK_END; + break; + } - if (!stream || (!stream->fp && stream->file_handle == INVALID_HANDLE_VALUE)) - return -1; - - switch (seek_position) - { - case RETRO_VFS_SEEK_POSITION_START: - if (stream->file_handle != INVALID_HANDLE_VALUE) - SetFilePointerEx(stream->file_handle, _offset, NULL, FILE_BEGIN); - else - stream->fp->Seek(offset); - break; - - case RETRO_VFS_SEEK_POSITION_CURRENT: - if (stream->file_handle != INVALID_HANDLE_VALUE) - SetFilePointerEx(stream->file_handle, _offset, NULL, FILE_CURRENT); - else - stream->fp->Seek(retro_vfs_file_tell_impl(stream) + offset); - break; - - case RETRO_VFS_SEEK_POSITION_END: - if (stream->file_handle != INVALID_HANDLE_VALUE) - SetFilePointerEx(stream->file_handle, _offset, NULL, FILE_END); - else - stream->fp->Seek(stream->fp->Size - offset); - break; - } - - /* For simplicity always flush the buffer on seek */ - stream->buffer_left = 0; - - return 0; + return retro_vfs_file_seek_internal(stream, offset, whence); } -int64_t retro_vfs_file_read_impl( - libretro_vfs_implementation_file *stream, void *s, uint64_t len) + + +//int64_t retro_vfs_file_read_impl( +// libretro_vfs_implementation_file *stream, void *s, uint64_t len) +//{ +// int64_t ret; +// int64_t bytes_read = 0; +// IBuffer^ buffer; +// +// if (!stream || (!stream->fp && stream->file_handle == INVALID_HANDLE_VALUE) || !s) +// return -1; +// +// if (stream->file_handle != INVALID_HANDLE_VALUE) +// { +// DWORD _bytes_read; +// ReadFile(stream->file_handle, (char*)s, len, &_bytes_read, NULL); +// return (int64_t)_bytes_read; +// } +// +// if (len <= stream->buffer_size) +// { +// /* Small read, use manually buffered I/O */ +// if (stream->buffer_left < len) +// { +// /* Exhaust the buffer */ +// memcpy(s, +// &stream->buffer[stream->buffer_fill - stream->buffer_left], +// stream->buffer_left); +// len -= stream->buffer_left; +// bytes_read += stream->buffer_left; +// stream->buffer_left = 0; +// +// /* Fill buffer */ +// stream->buffer_left = RunAsyncAndCatchErrors([&]() { +// return concurrency::create_task(stream->fp->ReadAsync(stream->bufferp, stream->bufferp->Capacity, InputStreamOptions::None)).then([&](IBuffer^ buf) { +// retro_assert(stream->bufferp == buf); +// return (int64_t)stream->bufferp->Length; +// }); +// }, -1); +// stream->buffer_fill = stream->buffer_left; +// +// if (stream->buffer_left == -1) +// { +// stream->buffer_left = 0; +// stream->buffer_fill = 0; +// return -1; +// } +// +// if (stream->buffer_left < len) +// { +// /* EOF */ +// memcpy(&((char*)s)[bytes_read], +// stream->buffer, stream->buffer_left); +// bytes_read += stream->buffer_left; +// stream->buffer_left = 0; +// return bytes_read; +// } +// +// memcpy(&((char*)s)[bytes_read], stream->buffer, len); +// bytes_read += len; +// stream->buffer_left -= len; +// return bytes_read; +// } +// +// /* Internal buffer already contains requested amount */ +// memcpy(s, +// &stream->buffer[stream->buffer_fill - stream->buffer_left], +// len); +// stream->buffer_left -= len; +// return len; +// } +// +// /* Big read exceeding buffer size, +// * exhaust small buffer and read rest in one go */ +// memcpy(s, &stream->buffer[stream->buffer_fill - stream->buffer_left], stream->buffer_left); +// len -= stream->buffer_left; +// bytes_read += stream->buffer_left; +// stream->buffer_left = 0; +// +// buffer = CreateNativeBuffer(&((char*)s)[bytes_read], len, 0); +// ret = RunAsyncAndCatchErrors([&]() { +// return concurrency::create_task(stream->fp->ReadAsync(buffer, buffer->Capacity - bytes_read, InputStreamOptions::None)).then([&](IBuffer^ buf) { +// retro_assert(buf == buffer); +// return (int64_t)buffer->Length; +// }); +// }, -1); +// +// if (ret == -1) +// return -1; +// return bytes_read + ret; +//} + +int64_t retro_vfs_file_read_impl(libretro_vfs_implementation_file* stream, + void* s, uint64_t len) { - int64_t ret; - int64_t bytes_read = 0; - IBuffer^ buffer; + if (!stream || !s) + return -1; - if (!stream || (!stream->fp && stream->file_handle == INVALID_HANDLE_VALUE) || !s) - return -1; - - if (stream->file_handle != INVALID_HANDLE_VALUE) - { - DWORD _bytes_read; - ReadFile(stream->file_handle, (char*)s, len, &_bytes_read, NULL); - return (int64_t)_bytes_read; - } - - if (len <= stream->buffer_size) - { - /* Small read, use manually buffered I/O */ - if (stream->buffer_left < len) - { - /* Exhaust the buffer */ - memcpy(s, - &stream->buffer[stream->buffer_fill - stream->buffer_left], - stream->buffer_left); - len -= stream->buffer_left; - bytes_read += stream->buffer_left; - stream->buffer_left = 0; - - /* Fill buffer */ - stream->buffer_left = RunAsyncAndCatchErrors([&]() { - return concurrency::create_task(stream->fp->ReadAsync(stream->bufferp, stream->bufferp->Capacity, InputStreamOptions::None)).then([&](IBuffer^ buf) { - retro_assert(stream->bufferp == buf); - return (int64_t)stream->bufferp->Length; - }); - }, -1); - stream->buffer_fill = stream->buffer_left; - - if (stream->buffer_left == -1) - { - stream->buffer_left = 0; - stream->buffer_fill = 0; - return -1; - } - - if (stream->buffer_left < len) - { - /* EOF */ - memcpy(&((char*)s)[bytes_read], - stream->buffer, stream->buffer_left); - bytes_read += stream->buffer_left; - stream->buffer_left = 0; - return bytes_read; - } - - memcpy(&((char*)s)[bytes_read], stream->buffer, len); - bytes_read += len; - stream->buffer_left -= len; - return bytes_read; - } - - /* Internal buffer already contains requested amount */ - memcpy(s, - &stream->buffer[stream->buffer_fill - stream->buffer_left], - len); - stream->buffer_left -= len; - return len; - } - - /* Big read exceeding buffer size, - * exhaust small buffer and read rest in one go */ - memcpy(s, &stream->buffer[stream->buffer_fill - stream->buffer_left], stream->buffer_left); - len -= stream->buffer_left; - bytes_read += stream->buffer_left; - stream->buffer_left = 0; - - buffer = CreateNativeBuffer(&((char*)s)[bytes_read], len, 0); - ret = RunAsyncAndCatchErrors([&]() { - return concurrency::create_task(stream->fp->ReadAsync(buffer, buffer->Capacity - bytes_read, InputStreamOptions::None)).then([&](IBuffer^ buf) { - retro_assert(buf == buffer); - return (int64_t)buffer->Length; - }); - }, -1); - - if (ret == -1) - return -1; - return bytes_read + ret; + if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) + { + return fread(s, 1, (size_t)len, stream->fp); + } + DWORD BytesRead; + return read(stream->fd, s, (size_t)len); + /*if (ReadFile(stream->fh, s, (DWORD)len, &BytesRead, NULL)) + { + return BytesRead; + } + else + { + return -1; + }*/ + // } -int64_t retro_vfs_file_write_impl( - libretro_vfs_implementation_file *stream, const void *s, uint64_t len) +//int64_t retro_vfs_file_write_impl( +// libretro_vfs_implementation_file *stream, const void *s, uint64_t len) +//{ +// IBuffer^ buffer; +// if (!stream || (!stream->fp && stream->file_handle == INVALID_HANDLE_VALUE) || !s) +// return -1; +// +// if (stream->file_handle != INVALID_HANDLE_VALUE) +// { +// DWORD bytes_written; +// WriteFile(stream->file_handle, s, len, &bytes_written, NULL); +// return (int64_t)bytes_written; +// } +// +// /* const_cast to remove const modifier is undefined behaviour, but the buffer is only read, should be safe */ +// buffer = CreateNativeBuffer(const_cast(s), len, len); +// return RunAsyncAndCatchErrors([&]() { +// return concurrency::create_task(stream->fp->WriteAsync(buffer)).then([&](unsigned int written) { +// return (int64_t)written; +// }); +// }, -1); +//} + +int64_t retro_vfs_file_write_impl(libretro_vfs_implementation_file* stream, const void* s, uint64_t len) { - IBuffer^ buffer; - if (!stream || (!stream->fp && stream->file_handle == INVALID_HANDLE_VALUE) || !s) - return -1; + if (!stream || (!stream->fp && stream->fh == INVALID_HANDLE_VALUE) || !s) + return -1; - if (stream->file_handle != INVALID_HANDLE_VALUE) - { - DWORD bytes_written; - WriteFile(stream->file_handle, s, len, &bytes_written, NULL); - return (int64_t)bytes_written; - } - /* const_cast to remove const modifier is undefined behaviour, but the buffer is only read, should be safe */ - buffer = CreateNativeBuffer(const_cast(s), len, len); - return RunAsyncAndCatchErrors([&]() { - return concurrency::create_task(stream->fp->WriteAsync(buffer)).then([&](unsigned int written) { - return (int64_t)written; - }); - }, -1); + if (stream->fh != INVALID_HANDLE_VALUE) + { + DWORD bytes_written; + WriteFile(stream->fh, s, len, &bytes_written, NULL); + return (int64_t)bytes_written; + } + + if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) + { + return fwrite(s, 1, (size_t)len, stream->fp); + } + + return write(stream->fd, s, (size_t)len); + //return write(stream->fd, s, (size_t)len); } -int retro_vfs_file_flush_impl(libretro_vfs_implementation_file *stream) +//int retro_vfs_file_flush_impl(libretro_vfs_implementation_file *stream) +//{ +// if (!stream || (!stream->fp && stream->file_handle == INVALID_HANDLE_VALUE) || !stream->fp) +// return -1; +// +// if (stream->file_handle != INVALID_HANDLE_VALUE) +// { +// FlushFileBuffers(stream->file_handle); +// return 0; +// } +// +// return RunAsyncAndCatchErrors([&]() { +// return concurrency::create_task(stream->fp->FlushAsync()).then([&](bool this_value_is_not_even_documented_wtf) { +// /* The bool value may be reporting an error or something, but just leave it alone for now */ +// /* https://github.com/MicrosoftDocs/winrt-api/issues/841 */ +// return 0; +// }); +// }, -1); +//} + +int retro_vfs_file_flush_impl(libretro_vfs_implementation_file* stream) { - if (!stream || (!stream->fp && stream->file_handle == INVALID_HANDLE_VALUE) || !stream->fp) - return -1; - - if (stream->file_handle != INVALID_HANDLE_VALUE) - { - FlushFileBuffers(stream->file_handle); - return 0; - } - - return RunAsyncAndCatchErrors([&]() { - return concurrency::create_task(stream->fp->FlushAsync()).then([&](bool this_value_is_not_even_documented_wtf) { - /* The bool value may be reporting an error or something, but just leave it alone for now */ - /* https://github.com/MicrosoftDocs/winrt-api/issues/841 */ - return 0; - }); - }, -1); + if (!stream) + return -1; + return fflush(stream->fp) == 0 ? 0 : -1; } int retro_vfs_file_remove_impl(const char *path) @@ -699,6 +792,260 @@ int retro_vfs_file_remove_impl(const char *path) return -1; } + +//libretro_vfs_implementation_file *retro_vfs_file_open_impl( +// const char *path, unsigned mode, unsigned hints) +//{ +// char dirpath[PATH_MAX_LENGTH]; +// char filename[PATH_MAX_LENGTH]; +// wchar_t *path_wide; +// wchar_t *dirpath_wide; +// wchar_t *filename_wide; +// Platform::String^ path_str; +// Platform::String^ filename_str; +// Platform::String^ dirpath_str; +// HANDLE file_handle = INVALID_HANDLE_VALUE; +// DWORD desireAccess; +// DWORD creationDisposition; +// +// if (!path || !*path) +// return NULL; +// +// /* Something tried to access files from current directory. +// * This is not allowed on UWP. */ +// if (!path_is_absolute(path)) +// return NULL; +// +// /* Trying to open a directory as file?! */ +// if (PATH_CHAR_IS_SLASH(path[strlen(path) - 1])) +// return NULL; +// +// dirpath[0] = filename[0] = '\0'; +// +// path_wide = utf8_to_utf16_string_alloc(path); +// windowsize_path(path_wide); +// path_str = ref new Platform::String(path_wide); +// free(path_wide); +// +// fill_pathname_basedir(dirpath, path, sizeof(dirpath)); +// dirpath_wide = utf8_to_utf16_string_alloc(dirpath); +// windowsize_path(dirpath_wide); +// dirpath_str = ref new Platform::String(dirpath_wide); +// free(dirpath_wide); +// +// fill_pathname_base(filename, path, sizeof(filename)); +// filename_wide = utf8_to_utf16_string_alloc(filename); +// filename_str = ref new Platform::String(filename_wide); +// free(filename_wide); +// +// retro_assert(!dirpath_str->IsEmpty() && !filename_str->IsEmpty()); +// +// /* Try Win32 first, this should work in AppData */ +// switch (mode) +// { +// case RETRO_VFS_FILE_ACCESS_READ_WRITE: +// desireAccess = GENERIC_READ | GENERIC_WRITE; +// break; +// case RETRO_VFS_FILE_ACCESS_WRITE: +// desireAccess = GENERIC_WRITE; +// break; +// case RETRO_VFS_FILE_ACCESS_READ: +// desireAccess = GENERIC_READ; +// break; +// } +// if (mode == RETRO_VFS_FILE_ACCESS_READ) +// { +// creationDisposition = OPEN_EXISTING; +// } +// else +// { +// creationDisposition = (mode & RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING) != 0 ? +// OPEN_ALWAYS : CREATE_ALWAYS; +// } +// path_str = "\\\\?\\" + path_str; +// file_handle = CreateFile2FromAppW(path_str->Data(), desireAccess, FILE_SHARE_READ, creationDisposition, NULL); +// +// if (file_handle != INVALID_HANDLE_VALUE) +// { +// libretro_vfs_implementation_file* stream = (libretro_vfs_implementation_file*)calloc(1, sizeof(*stream)); +// if (!stream) +// return (libretro_vfs_implementation_file*)NULL; +// +// stream->orig_path = strdup(path); +// stream->fp = nullptr; +// stream->file_handle = file_handle; +// stream->buffer_left = 0; +// stream->buffer_fill = 0; +// return stream; +// } +// return NULL; +//} + +libretro_vfs_implementation_file* retro_vfs_file_open_impl( + const char* path, unsigned mode, unsigned hints) +{ +#if defined(VFS_FRONTEND) || defined(HAVE_CDROM) + int path_len = (int)strlen(path); +#endif +#ifdef VFS_FRONTEND + const char* dumb_prefix = "vfsonly://"; + size_t dumb_prefix_siz = STRLEN_CONST("vfsonly://"); + int dumb_prefix_len = (int)dumb_prefix_siz; +#endif + wchar_t* path_wide; + int flags = 0; + const char* mode_str = NULL; + libretro_vfs_implementation_file* stream = + (libretro_vfs_implementation_file*) + malloc(sizeof(*stream)); + + if (!stream) + return NULL; + + stream->fd = 0; + stream->hints = hints; + stream->size = 0; + stream->buf = NULL; + stream->fp = NULL; + stream->fh = 0; + stream->orig_path = NULL; + stream->mappos = 0; + stream->mapsize = 0; + stream->mapped = NULL; + stream->scheme = VFS_SCHEME_NONE; + +#ifdef VFS_FRONTEND + if (path_len >= dumb_prefix_len) + if (!memcmp(path, dumb_prefix, dumb_prefix_len)) + path += dumb_prefix_siz; +#endif + + path_wide = utf8_to_utf16_string_alloc(path); + windowsize_path(path_wide); + std::wstring path_wstring = path_wide; + free(path_wide); + while (true) { + size_t p = path_wstring.find(L"\\\\"); + if (p == std::wstring::npos) break; + path_wstring.replace(p, 2, L"\\"); + } + + path_wstring = L"\\\\?\\" + path_wstring; + stream->orig_path = strdup(path); + + stream->hints &= ~RETRO_VFS_FILE_ACCESS_HINT_FREQUENT_ACCESS; + + DWORD desireAccess; + DWORD creationDisposition; + + switch (mode) + { + case RETRO_VFS_FILE_ACCESS_READ: + mode_str = "rb"; + flags = O_RDONLY | O_BINARY; + break; + + case RETRO_VFS_FILE_ACCESS_WRITE: + mode_str = "wb"; + flags = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY; + break; + + case RETRO_VFS_FILE_ACCESS_READ_WRITE: + mode_str = "w+b"; + flags = O_RDWR | O_CREAT | O_TRUNC | O_BINARY; + break; + + case RETRO_VFS_FILE_ACCESS_WRITE | RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING: + case RETRO_VFS_FILE_ACCESS_READ_WRITE | RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING: + mode_str = "r+b"; + flags = O_RDWR | O_BINARY; + break; + + default: + goto error; + } + + switch (mode) + { + case RETRO_VFS_FILE_ACCESS_READ_WRITE: + desireAccess = GENERIC_READ | GENERIC_WRITE; + break; + case RETRO_VFS_FILE_ACCESS_WRITE: + desireAccess = GENERIC_WRITE; + break; + case RETRO_VFS_FILE_ACCESS_READ: + desireAccess = GENERIC_READ; + break; + } + if (mode == RETRO_VFS_FILE_ACCESS_READ) + { + creationDisposition = OPEN_EXISTING; + } + else + { + creationDisposition = (mode & RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING) != 0 ? + OPEN_ALWAYS : CREATE_ALWAYS; + } + HANDLE file_handle = CreateFile2FromAppW(path_wstring.data(), desireAccess, FILE_SHARE_READ, creationDisposition, NULL); + if (file_handle != INVALID_HANDLE_VALUE) + { + stream->fh = file_handle; + } + else + { + goto error; + } + stream->fd = _open_osfhandle((uint64)stream->fh, flags); + if (stream->fd == -1) + goto error; + else + { + FILE* fp; + fp = _fdopen(stream->fd, mode_str); + + if (!fp) + { + int gamingerror = errno; + goto error; + } + stream->fp = fp; + } + /* Regarding setvbuf: + * + * https://www.freebsd.org/cgi/man.cgi?query=setvbuf&apropos=0&sektion=0&manpath=FreeBSD+11.1-RELEASE&arch=default&format=html + * + * If the size argument is not zero but buf is NULL, + * a buffer of the given size will be allocated immediately, and + * released on close. This is an extension to ANSI C. + * + * Since C89 does not support specifying a NULL buffer + * with a non-zero size, we create and track our own buffer for it. + */ + /* TODO: this is only useful for a few platforms, + * find which and add ifdef */ + if (stream->scheme != VFS_SCHEME_CDROM) + { + stream->buf = (char*)calloc(1, 0x4000); + if (stream->fp) + setvbuf(stream->fp, stream->buf, _IOFBF, 0x4000); + } + + + { + retro_vfs_file_seek_internal(stream, 0, SEEK_SET); + retro_vfs_file_seek_internal(stream, 0, SEEK_END); + + stream->size = retro_vfs_file_tell_impl(stream); + + retro_vfs_file_seek_internal(stream, 0, SEEK_SET); + } + return stream; + +error: + retro_vfs_file_close_impl(stream); + return NULL; +} + /* TODO: this may not work if trying to move a directory */ /*int retro_vfs_file_rename_impl(const char* old_path, const char* new_path) { From d85919d0e3538fc80c3ea468ba48ffc8a37499ba Mon Sep 17 00:00:00 2001 From: Tunip3 Date: Thu, 30 Sep 2021 18:59:20 +0100 Subject: [PATCH 2/2] delete functions that were commented out --- .../vfs/vfs_implementation_uwp.cpp | 416 ------------------ 1 file changed, 416 deletions(-) diff --git a/libretro-common/vfs/vfs_implementation_uwp.cpp b/libretro-common/vfs/vfs_implementation_uwp.cpp index 3fbf029103..7aeaa3bb0c 100644 --- a/libretro-common/vfs/vfs_implementation_uwp.cpp +++ b/libretro-common/vfs/vfs_implementation_uwp.cpp @@ -320,21 +320,6 @@ HRESULT GetHandleFromStorageFile(Windows::Storage::StorageFile^ file, HANDLE* ha return E_FAIL; } -//#ifdef VFS_FRONTEND -//struct retro_vfs_file_handle -//#else -//struct libretro_vfs_implementation_file -//#endif -//{ -// IRandomAccessStream^ fp; -// IBuffer^ bufferp; -// HANDLE file_handle; -// char* buffer; -// char* orig_path; -// size_t buffer_size; -// int buffer_left; -// size_t buffer_fill; -//}; #ifdef VFS_FRONTEND struct retro_vfs_file_handle @@ -357,26 +342,6 @@ struct libretro_vfs_implementation_file #define RFILE_HINT_UNBUFFERED (1 << 8) - - -//int retro_vfs_file_close_impl(libretro_vfs_implementation_file *stream) -//{ -// if (!stream || (!stream->fp && stream->file_handle == INVALID_HANDLE_VALUE)) -// return -1; -// -// if (stream->file_handle != INVALID_HANDLE_VALUE) -// CloseHandle(stream->file_handle); -// else -// { -// /* Apparently, this is how you close a file in WinRT */ -// /* Yes, really */ -// stream->fp = nullptr; -// free(stream->buffer); -// } -// -// return 0; -//} - int retro_vfs_file_close_impl(libretro_vfs_implementation_file* stream) { if (!stream) @@ -408,32 +373,12 @@ int retro_vfs_file_close_impl(libretro_vfs_implementation_file* stream) return 0; } -//int retro_vfs_file_error_impl(libretro_vfs_implementation_file *stream) -//{ -// return false; /* TODO */ -//} int retro_vfs_file_error_impl(libretro_vfs_implementation_file* stream) { return ferror(stream->fp); } -//int64_t retro_vfs_file_size_impl(libretro_vfs_implementation_file *stream) -//{ -// if (!stream || (!stream->fp && stream->file_handle == INVALID_HANDLE_VALUE)) -// return 0; -// -// if (stream->file_handle != INVALID_HANDLE_VALUE) -// { -// LARGE_INTEGER sz; -// if (GetFileSizeEx(stream->file_handle, &sz)) -// return sz.QuadPart; -// return 0; -// } -// -// return stream->fp->Size; -//} - int64_t retro_vfs_file_size_impl(libretro_vfs_implementation_file* stream) { if (stream) @@ -441,25 +386,6 @@ int64_t retro_vfs_file_size_impl(libretro_vfs_implementation_file* stream) return 0; } -//int64_t retro_vfs_file_truncate_impl(libretro_vfs_implementation_file *stream, int64_t length) -//{ -// if (!stream || (!stream->fp && stream->file_handle == INVALID_HANDLE_VALUE)) -// return -1; -// -// if (stream->file_handle != INVALID_HANDLE_VALUE) -// { -// int64_t p = retro_vfs_file_tell_impl(stream); -// retro_vfs_file_seek_impl(stream, length, RETRO_VFS_SEEK_POSITION_START); -// SetEndOfFile(stream->file_handle); -// -// if (p < length) -// retro_vfs_file_seek_impl(stream, p, RETRO_VFS_SEEK_POSITION_START); -// } -// else -// stream->fp->Size = length; -// -// return 0; -//} int64_t retro_vfs_file_truncate_impl(libretro_vfs_implementation_file* stream, int64_t length) { @@ -472,24 +398,6 @@ int64_t retro_vfs_file_truncate_impl(libretro_vfs_implementation_file* stream, i return 0; } -//int64_t retro_vfs_file_tell_impl(libretro_vfs_implementation_file *stream) -//{ -// LARGE_INTEGER _offset; -// LARGE_INTEGER out; -// _offset.QuadPart = 0; -// -// if (!stream || (!stream->fp && stream->file_handle == INVALID_HANDLE_VALUE)) -// return -1; -// -// if (stream->file_handle != INVALID_HANDLE_VALUE) -// { -// SetFilePointerEx(stream->file_handle, _offset, &out, FILE_CURRENT); -// return out.QuadPart; -// } -// -// return stream->fp->Position - stream->buffer_left; -//} - int64_t retro_vfs_file_tell_impl(libretro_vfs_implementation_file* stream) { @@ -506,46 +414,6 @@ int64_t retro_vfs_file_tell_impl(libretro_vfs_implementation_file* stream) return 0; } -//int64_t retro_vfs_file_seek_impl( -// libretro_vfs_implementation_file *stream, -// int64_t offset, int seek_position) -//{ -// LARGE_INTEGER _offset; -// _offset.QuadPart = offset; -// -// if (!stream || (!stream->fp && stream->file_handle == INVALID_HANDLE_VALUE)) -// return -1; -// -// switch (seek_position) -// { -// case RETRO_VFS_SEEK_POSITION_START: -// if (stream->file_handle != INVALID_HANDLE_VALUE) -// SetFilePointerEx(stream->file_handle, _offset, NULL, FILE_BEGIN); -// else -// stream->fp->Seek(offset); -// break; -// -// case RETRO_VFS_SEEK_POSITION_CURRENT: -// if (stream->file_handle != INVALID_HANDLE_VALUE) -// SetFilePointerEx(stream->file_handle, _offset, NULL, FILE_CURRENT); -// else -// stream->fp->Seek(retro_vfs_file_tell_impl(stream) + offset); -// break; -// -// case RETRO_VFS_SEEK_POSITION_END: -// if (stream->file_handle != INVALID_HANDLE_VALUE) -// SetFilePointerEx(stream->file_handle, _offset, NULL, FILE_END); -// else -// stream->fp->Seek(stream->fp->Size - offset); -// break; -// } -// -// /* For simplicity always flush the buffer on seek */ -// stream->buffer_left = 0; -// -// return 0; -//} - int64_t retro_vfs_file_seek_internal( libretro_vfs_implementation_file* stream, int64_t offset, int whence) @@ -585,98 +453,6 @@ int64_t retro_vfs_file_seek_impl(libretro_vfs_implementation_file* stream, return retro_vfs_file_seek_internal(stream, offset, whence); } - - -//int64_t retro_vfs_file_read_impl( -// libretro_vfs_implementation_file *stream, void *s, uint64_t len) -//{ -// int64_t ret; -// int64_t bytes_read = 0; -// IBuffer^ buffer; -// -// if (!stream || (!stream->fp && stream->file_handle == INVALID_HANDLE_VALUE) || !s) -// return -1; -// -// if (stream->file_handle != INVALID_HANDLE_VALUE) -// { -// DWORD _bytes_read; -// ReadFile(stream->file_handle, (char*)s, len, &_bytes_read, NULL); -// return (int64_t)_bytes_read; -// } -// -// if (len <= stream->buffer_size) -// { -// /* Small read, use manually buffered I/O */ -// if (stream->buffer_left < len) -// { -// /* Exhaust the buffer */ -// memcpy(s, -// &stream->buffer[stream->buffer_fill - stream->buffer_left], -// stream->buffer_left); -// len -= stream->buffer_left; -// bytes_read += stream->buffer_left; -// stream->buffer_left = 0; -// -// /* Fill buffer */ -// stream->buffer_left = RunAsyncAndCatchErrors([&]() { -// return concurrency::create_task(stream->fp->ReadAsync(stream->bufferp, stream->bufferp->Capacity, InputStreamOptions::None)).then([&](IBuffer^ buf) { -// retro_assert(stream->bufferp == buf); -// return (int64_t)stream->bufferp->Length; -// }); -// }, -1); -// stream->buffer_fill = stream->buffer_left; -// -// if (stream->buffer_left == -1) -// { -// stream->buffer_left = 0; -// stream->buffer_fill = 0; -// return -1; -// } -// -// if (stream->buffer_left < len) -// { -// /* EOF */ -// memcpy(&((char*)s)[bytes_read], -// stream->buffer, stream->buffer_left); -// bytes_read += stream->buffer_left; -// stream->buffer_left = 0; -// return bytes_read; -// } -// -// memcpy(&((char*)s)[bytes_read], stream->buffer, len); -// bytes_read += len; -// stream->buffer_left -= len; -// return bytes_read; -// } -// -// /* Internal buffer already contains requested amount */ -// memcpy(s, -// &stream->buffer[stream->buffer_fill - stream->buffer_left], -// len); -// stream->buffer_left -= len; -// return len; -// } -// -// /* Big read exceeding buffer size, -// * exhaust small buffer and read rest in one go */ -// memcpy(s, &stream->buffer[stream->buffer_fill - stream->buffer_left], stream->buffer_left); -// len -= stream->buffer_left; -// bytes_read += stream->buffer_left; -// stream->buffer_left = 0; -// -// buffer = CreateNativeBuffer(&((char*)s)[bytes_read], len, 0); -// ret = RunAsyncAndCatchErrors([&]() { -// return concurrency::create_task(stream->fp->ReadAsync(buffer, buffer->Capacity - bytes_read, InputStreamOptions::None)).then([&](IBuffer^ buf) { -// retro_assert(buf == buffer); -// return (int64_t)buffer->Length; -// }); -// }, -1); -// -// if (ret == -1) -// return -1; -// return bytes_read + ret; -//} - int64_t retro_vfs_file_read_impl(libretro_vfs_implementation_file* stream, void* s, uint64_t len) { @@ -689,39 +465,8 @@ int64_t retro_vfs_file_read_impl(libretro_vfs_implementation_file* stream, } DWORD BytesRead; return read(stream->fd, s, (size_t)len); - /*if (ReadFile(stream->fh, s, (DWORD)len, &BytesRead, NULL)) - { - return BytesRead; - } - else - { - return -1; - }*/ - // } -//int64_t retro_vfs_file_write_impl( -// libretro_vfs_implementation_file *stream, const void *s, uint64_t len) -//{ -// IBuffer^ buffer; -// if (!stream || (!stream->fp && stream->file_handle == INVALID_HANDLE_VALUE) || !s) -// return -1; -// -// if (stream->file_handle != INVALID_HANDLE_VALUE) -// { -// DWORD bytes_written; -// WriteFile(stream->file_handle, s, len, &bytes_written, NULL); -// return (int64_t)bytes_written; -// } -// -// /* const_cast to remove const modifier is undefined behaviour, but the buffer is only read, should be safe */ -// buffer = CreateNativeBuffer(const_cast(s), len, len); -// return RunAsyncAndCatchErrors([&]() { -// return concurrency::create_task(stream->fp->WriteAsync(buffer)).then([&](unsigned int written) { -// return (int64_t)written; -// }); -// }, -1); -//} int64_t retro_vfs_file_write_impl(libretro_vfs_implementation_file* stream, const void* s, uint64_t len) { @@ -745,26 +490,6 @@ int64_t retro_vfs_file_write_impl(libretro_vfs_implementation_file* stream, cons //return write(stream->fd, s, (size_t)len); } -//int retro_vfs_file_flush_impl(libretro_vfs_implementation_file *stream) -//{ -// if (!stream || (!stream->fp && stream->file_handle == INVALID_HANDLE_VALUE) || !stream->fp) -// return -1; -// -// if (stream->file_handle != INVALID_HANDLE_VALUE) -// { -// FlushFileBuffers(stream->file_handle); -// return 0; -// } -// -// return RunAsyncAndCatchErrors([&]() { -// return concurrency::create_task(stream->fp->FlushAsync()).then([&](bool this_value_is_not_even_documented_wtf) { -// /* The bool value may be reporting an error or something, but just leave it alone for now */ -// /* https://github.com/MicrosoftDocs/winrt-api/issues/841 */ -// return 0; -// }); -// }, -1); -//} - int retro_vfs_file_flush_impl(libretro_vfs_implementation_file* stream) { if (!stream) @@ -792,95 +517,6 @@ int retro_vfs_file_remove_impl(const char *path) return -1; } - -//libretro_vfs_implementation_file *retro_vfs_file_open_impl( -// const char *path, unsigned mode, unsigned hints) -//{ -// char dirpath[PATH_MAX_LENGTH]; -// char filename[PATH_MAX_LENGTH]; -// wchar_t *path_wide; -// wchar_t *dirpath_wide; -// wchar_t *filename_wide; -// Platform::String^ path_str; -// Platform::String^ filename_str; -// Platform::String^ dirpath_str; -// HANDLE file_handle = INVALID_HANDLE_VALUE; -// DWORD desireAccess; -// DWORD creationDisposition; -// -// if (!path || !*path) -// return NULL; -// -// /* Something tried to access files from current directory. -// * This is not allowed on UWP. */ -// if (!path_is_absolute(path)) -// return NULL; -// -// /* Trying to open a directory as file?! */ -// if (PATH_CHAR_IS_SLASH(path[strlen(path) - 1])) -// return NULL; -// -// dirpath[0] = filename[0] = '\0'; -// -// path_wide = utf8_to_utf16_string_alloc(path); -// windowsize_path(path_wide); -// path_str = ref new Platform::String(path_wide); -// free(path_wide); -// -// fill_pathname_basedir(dirpath, path, sizeof(dirpath)); -// dirpath_wide = utf8_to_utf16_string_alloc(dirpath); -// windowsize_path(dirpath_wide); -// dirpath_str = ref new Platform::String(dirpath_wide); -// free(dirpath_wide); -// -// fill_pathname_base(filename, path, sizeof(filename)); -// filename_wide = utf8_to_utf16_string_alloc(filename); -// filename_str = ref new Platform::String(filename_wide); -// free(filename_wide); -// -// retro_assert(!dirpath_str->IsEmpty() && !filename_str->IsEmpty()); -// -// /* Try Win32 first, this should work in AppData */ -// switch (mode) -// { -// case RETRO_VFS_FILE_ACCESS_READ_WRITE: -// desireAccess = GENERIC_READ | GENERIC_WRITE; -// break; -// case RETRO_VFS_FILE_ACCESS_WRITE: -// desireAccess = GENERIC_WRITE; -// break; -// case RETRO_VFS_FILE_ACCESS_READ: -// desireAccess = GENERIC_READ; -// break; -// } -// if (mode == RETRO_VFS_FILE_ACCESS_READ) -// { -// creationDisposition = OPEN_EXISTING; -// } -// else -// { -// creationDisposition = (mode & RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING) != 0 ? -// OPEN_ALWAYS : CREATE_ALWAYS; -// } -// path_str = "\\\\?\\" + path_str; -// file_handle = CreateFile2FromAppW(path_str->Data(), desireAccess, FILE_SHARE_READ, creationDisposition, NULL); -// -// if (file_handle != INVALID_HANDLE_VALUE) -// { -// libretro_vfs_implementation_file* stream = (libretro_vfs_implementation_file*)calloc(1, sizeof(*stream)); -// if (!stream) -// return (libretro_vfs_implementation_file*)NULL; -// -// stream->orig_path = strdup(path); -// stream->fp = nullptr; -// stream->file_handle = file_handle; -// stream->buffer_left = 0; -// stream->buffer_fill = 0; -// return stream; -// } -// return NULL; -//} - libretro_vfs_implementation_file* retro_vfs_file_open_impl( const char* path, unsigned mode, unsigned hints) { @@ -1046,58 +682,6 @@ error: return NULL; } -/* TODO: this may not work if trying to move a directory */ -/*int retro_vfs_file_rename_impl(const char* old_path, const char* new_path) -{ - char new_file_name[PATH_MAX_LENGTH]; - char new_dir_path[PATH_MAX_LENGTH]; - wchar_t *new_file_name_wide; - wchar_t *old_path_wide, *new_dir_path_wide; - Platform::String^ old_path_str; - Platform::String^ new_dir_path_str; - Platform::String^ new_file_name_str; - - if (!old_path || !*old_path || !new_path || !*new_path) - return -1; - - new_file_name[0] = '\0'; - new_dir_path [0] = '\0'; - - old_path_wide = utf8_to_utf16_string_alloc(old_path); - old_path_str = ref new Platform::String(old_path_wide); - free(old_path_wide); - - fill_pathname_basedir(new_dir_path, new_path, sizeof(new_dir_path)); - new_dir_path_wide = utf8_to_utf16_string_alloc(new_dir_path); - windowsize_path(new_dir_path_wide); - new_dir_path_str = ref new Platform::String(new_dir_path_wide); - free(new_dir_path_wide); - - fill_pathname_base(new_file_name, new_path, sizeof(new_file_name)); - new_file_name_wide = utf8_to_utf16_string_alloc(new_file_name); - new_file_name_str = ref new Platform::String(new_file_name_wide); - free(new_file_name_wide); - - retro_assert(!old_path_str->IsEmpty() && !new_dir_path_str->IsEmpty() && !new_file_name_str->IsEmpty()); - - return RunAsyncAndCatchErrors([&]() { - concurrency::task old_file_task = concurrency::create_task(LocateStorageItem(old_path_str)); - concurrency::task new_dir_task = concurrency::create_task(LocateStorageItem(new_dir_path_str)); - return concurrency::create_task([&] { - // Run these two tasks in parallel - // TODO: There may be some cleaner way to express this - concurrency::task_group group; - group.run([&] { return old_file_task; }); - group.run([&] { return new_dir_task; }); - group.wait(); - }).then([&]() { - return old_file_task.get()->MoveAsync(new_dir_task.get(), new_file_name_str, NameCollisionOption::ReplaceExisting); - }).then([&]() { - return 0; - }); - }, -1); -}*/ - //this is enables you to copy access permissions from one file/folder to another //however depending on the target and where the file is being transferred to and from it may not be needed. //(use disgression)