Skip to content

Commit b4be5f5

Browse files
committed
Add SMB implementation to UWP
1 parent bc4ab25 commit b4be5f5

File tree

1 file changed

+157
-11
lines changed

1 file changed

+157
-11
lines changed

libretro-common/vfs/vfs_implementation_uwp.cpp

Lines changed: 157 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@
4949
#include <retro_environment.h>
5050
#include <uwp/std_filesystem_compat.h>
5151

52+
#ifdef HAVE_SMBCLIENT
53+
#include "vfs_implementation_smb.h"
54+
#endif
55+
5256
namespace
5357
{
5458
/* UWP deals with paths containing / instead of
@@ -76,6 +80,13 @@ int retro_vfs_file_close_impl(libretro_vfs_implementation_file* stream)
7680
if (!stream)
7781
return -1;
7882

83+
#ifdef HAVE_SMBCLIENT
84+
if (stream->scheme == VFS_SCHEME_SMB)
85+
{
86+
retro_vfs_file_close_smb(stream);
87+
}
88+
#endif
89+
7990
if (stream->fp)
8091
fclose(stream->fp);
8192

@@ -94,6 +105,11 @@ int retro_vfs_file_close_impl(libretro_vfs_implementation_file* stream)
94105

95106
int retro_vfs_file_error_impl(libretro_vfs_implementation_file* stream)
96107
{
108+
#ifdef HAVE_SMBCLIENT
109+
if (stream->scheme == VFS_SCHEME_SMB)
110+
return retro_vfs_file_error_smb(stream);
111+
#endif
112+
97113
return ferror(stream->fp);
98114
}
99115

@@ -117,7 +133,13 @@ int64_t retro_vfs_file_tell_impl(libretro_vfs_implementation_file* stream)
117133
return -1;
118134

119135
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
136+
{
137+
#ifdef HAVE_SMBCLIENT
138+
if (stream->scheme == VFS_SCHEME_SMB)
139+
return retro_vfs_file_tell_smb(stream);
140+
#endif
120141
return _ftelli64(stream->fp);
142+
}
121143
if (lseek(stream->fd, 0, SEEK_CUR) < 0)
122144
return -1;
123145

@@ -132,7 +154,13 @@ int64_t retro_vfs_file_seek_internal(
132154
return -1;
133155

134156
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
157+
{
158+
#ifdef HAVE_SMBCLIENT
159+
if (stream->scheme == VFS_SCHEME_SMB)
160+
return retro_vfs_file_seek_smb(stream, offset, whence);
161+
#endif
135162
return _fseeki64(stream->fp, offset, whence);
163+
}
136164
if (lseek(stream->fd, (off_t)offset, whence) < 0)
137165
return -1;
138166

@@ -148,25 +176,51 @@ int64_t retro_vfs_file_seek_impl(libretro_vfs_implementation_file* stream,
148176
int64_t retro_vfs_file_read_impl(libretro_vfs_implementation_file* stream,
149177
void* s, uint64_t len)
150178
{
151-
if (!stream || (!stream->fp && stream->fh == INVALID_HANDLE_VALUE) || !s)
152-
return -1;
179+
if (!stream)
180+
return -1;
153181

154-
if (stream->fh != INVALID_HANDLE_VALUE)
155-
{
156-
DWORD _bytes_read;
157-
ReadFile(stream->fh, (char*)s, len, &_bytes_read, NULL);
158-
return (int64_t)_bytes_read;
159-
}
182+
#ifdef HAVE_SMBCLIENT
183+
if (stream->scheme == VFS_SCHEME_SMB)
184+
return retro_vfs_file_read_smb(stream, s, len);
185+
#endif
186+
187+
if ((!stream->fp && stream->fh == INVALID_HANDLE_VALUE) || !s)
188+
return -1;
189+
190+
if (stream->fh != INVALID_HANDLE_VALUE)
191+
{
192+
DWORD _bytes_read;
193+
ReadFile(stream->fh, (char*)s, len, &_bytes_read, NULL);
194+
return (int64_t)_bytes_read;
195+
}
160196

161197
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
162-
return fread(s, 1, (size_t)len, stream->fp);
198+
return fread(s, 1, (size_t)len, stream->fp);
163199
return read(stream->fd, s, (size_t)len);
164200
}
165201

166202

167203
int64_t retro_vfs_file_write_impl(libretro_vfs_implementation_file* stream, const void* s, uint64_t len)
168204
{
169-
if (!stream || (!stream->fp && stream->fh == INVALID_HANDLE_VALUE) || !s)
205+
if (!stream)
206+
return -1;
207+
208+
#ifdef HAVE_SMBCLIENT
209+
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0 &&
210+
stream->scheme == VFS_SCHEME_SMB)
211+
{
212+
int64_t pos = 0;
213+
ssize_t ret = -1;
214+
215+
pos = retro_vfs_file_tell_smb(stream);
216+
ret = retro_vfs_file_write_smb(stream, s, len);
217+
if (ret != -1 && pos + ret > stream->size)
218+
stream->size = pos + ret;
219+
return ret;
220+
}
221+
#endif
222+
223+
if ((!stream->fp && stream->fh == INVALID_HANDLE_VALUE) || !s)
170224
return -1;
171225

172226
if (stream->fh != INVALID_HANDLE_VALUE)
@@ -237,6 +291,9 @@ libretro_vfs_implementation_file* retro_vfs_file_open_impl(
237291
stream->mapsize = 0;
238292
stream->mapped = NULL;
239293
stream->scheme = VFS_SCHEME_NONE;
294+
#ifdef HAVE_SMBCLIENT
295+
stream->smb_fh = 0;
296+
#endif
240297

241298
#ifdef VFS_FRONTEND
242299
if ( path
@@ -253,6 +310,20 @@ libretro_vfs_implementation_file* retro_vfs_file_open_impl(
253310
path += sizeof("vfsonly://")-1;
254311
#endif
255312

313+
#ifdef HAVE_SMBCLIENT
314+
if ( path
315+
&& path[0] == 's'
316+
&& path[1] == 'm'
317+
&& path[2] == 'b'
318+
&& path[3] == ':'
319+
&& path[4] == '/'
320+
&& path[5] == '/'
321+
&& path[6] != '\0')
322+
{
323+
stream->scheme = VFS_SCHEME_SMB;
324+
}
325+
#endif
326+
256327
path_wide = utf8_to_utf16_string_alloc(path);
257328
windowsize_path(path_wide);
258329
path_wstring = path_wide;
@@ -317,6 +388,16 @@ libretro_vfs_implementation_file* retro_vfs_file_open_impl(
317388
? OPEN_ALWAYS
318389
: CREATE_ALWAYS;
319390

391+
#ifdef HAVE_SMBCLIENT
392+
if (stream->scheme == VFS_SCHEME_SMB)
393+
{
394+
if (!retro_vfs_file_open_smb(stream, path, mode, hints))
395+
goto error;
396+
397+
return stream;
398+
}
399+
#endif
400+
320401
if ((file_handle = CreateFile2FromAppW(path_wstring.data(), desireAccess,
321402
FILE_SHARE_READ, creationDisposition, NULL)) == INVALID_HANDLE_VALUE)
322403
goto error;
@@ -631,6 +712,10 @@ struct libretro_vfs_implementation_dir
631712
HANDLE directory;
632713
bool next;
633714
char path[PATH_MAX_LENGTH];
715+
#ifdef HAVE_SMBCLIENT
716+
intptr_t smb_directory;
717+
char smb_path[PATH_MAX_LENGTH];
718+
#endif
634719
};
635720

636721
libretro_vfs_implementation_dir* retro_vfs_opendir_impl(
@@ -653,6 +738,23 @@ libretro_vfs_implementation_dir* retro_vfs_opendir_impl(
653738

654739
_len = strlcpy(path_buf, name, sizeof(path_buf));
655740

741+
#ifdef HAVE_SMBCLIENT
742+
if (name[0]=='s' && name[1]=='m' && name[2]=='b' &&
743+
name[3]==':' && name[4]=='/' && name[5]=='/' && name[6] != '\0')
744+
{
745+
intptr_t dh = retro_vfs_opendir_smb(name, include_hidden);
746+
if (dh < 0)
747+
{
748+
free(rdir->orig_path);
749+
free(rdir);
750+
return NULL;
751+
}
752+
rdir->smb_directory = dh;
753+
rdir->smb_path[0] = '\0';
754+
return rdir;
755+
}
756+
#endif
757+
656758
/* Non-NT platforms don't like extra slashes in the path */
657759
if (path_buf[_len - 1] != '\\')
658760
path_buf[_len++] = '\\';
@@ -682,6 +784,22 @@ libretro_vfs_implementation_dir* retro_vfs_opendir_impl(
682784

683785
bool retro_vfs_readdir_impl(libretro_vfs_implementation_dir* rdir)
684786
{
787+
#ifdef HAVE_SMBCLIENT
788+
if (rdir->smb_directory != 0)
789+
{
790+
struct smbc_dirent *de = retro_vfs_readdir_smb(rdir->smb_directory);
791+
if (!de)
792+
return false;
793+
strlcpy(rdir->smb_path, de->name, sizeof(rdir->smb_path));
794+
return true;
795+
}
796+
/* If we opened an SMB path but failed, do not fall through to native readdir */
797+
if (rdir->orig_path &&
798+
rdir->orig_path[0]=='s' && rdir->orig_path[1]=='m' && rdir->orig_path[2]=='b' &&
799+
rdir->orig_path[3]==':' && rdir->orig_path[4]=='/' && rdir->orig_path[5]=='/' )
800+
return false;
801+
#endif
802+
685803
if (rdir->next)
686804
return (FindNextFileW(rdir->directory, &rdir->entry) != 0);
687805

@@ -691,6 +809,10 @@ bool retro_vfs_readdir_impl(libretro_vfs_implementation_dir* rdir)
691809

692810
const char* retro_vfs_dirent_get_name_impl(libretro_vfs_implementation_dir* rdir)
693811
{
812+
#ifdef HAVE_SMBCLIENT
813+
if (rdir->smb_directory != 0)
814+
return rdir->smb_path;
815+
#endif
694816
char* name = utf16_to_utf8_string_alloc(rdir->entry.cFileName);
695817
memset(rdir->entry.cFileName, 0, sizeof(rdir->entry.cFileName));
696818
strlcpy((char*)rdir->entry.cFileName, name, sizeof(rdir->entry.cFileName));
@@ -701,6 +823,22 @@ const char* retro_vfs_dirent_get_name_impl(libretro_vfs_implementation_dir* rdir
701823

702824
bool retro_vfs_dirent_is_dir_impl(libretro_vfs_implementation_dir* rdir)
703825
{
826+
#ifdef HAVE_SMBCLIENT
827+
if (rdir->smb_directory != 0)
828+
{
829+
char full[PATH_MAX_LENGTH];
830+
const char *name = retro_vfs_dirent_get_name_impl(rdir);
831+
832+
if (!name)
833+
return false;
834+
835+
fill_pathname_join_special(full, rdir->orig_path, name, sizeof(full));
836+
int32_t sz = 0;
837+
int st = retro_vfs_stat_smb(full, &sz);
838+
839+
return (st & RETRO_VFS_STAT_IS_DIRECTORY) != 0;
840+
}
841+
#endif
704842
const WIN32_FIND_DATA* entry = (const WIN32_FIND_DATA*)&rdir->entry;
705843
return entry->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
706844
}
@@ -710,7 +848,15 @@ int retro_vfs_closedir_impl(libretro_vfs_implementation_dir* rdir)
710848
if (!rdir)
711849
return -1;
712850

713-
if (rdir->directory != INVALID_HANDLE_VALUE)
851+
#ifdef HAVE_SMBCLIENT
852+
if (rdir->smb_directory != 0)
853+
{
854+
retro_vfs_closedir_smb(rdir->smb_directory);
855+
rdir->smb_directory = 0;
856+
}
857+
#endif
858+
859+
if (rdir->directory && rdir->directory != INVALID_HANDLE_VALUE)
714860
FindClose(rdir->directory);
715861

716862
if (rdir->orig_path)

0 commit comments

Comments
 (0)