Skip to content

Commit 2ecc653

Browse files
committed
Add SMB implementation to UWP
1 parent e914a33 commit 2ecc653

File tree

1 file changed

+156
-11
lines changed

1 file changed

+156
-11
lines changed

libretro-common/vfs/vfs_implementation_uwp.cpp

Lines changed: 156 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,11 @@ 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+
retro_vfs_file_close_smb(stream);
86+
#endif
87+
7988
if (stream->fp)
8089
fclose(stream->fp);
8190

@@ -94,6 +103,11 @@ int retro_vfs_file_close_impl(libretro_vfs_implementation_file* stream)
94103

95104
int retro_vfs_file_error_impl(libretro_vfs_implementation_file* stream)
96105
{
106+
#ifdef HAVE_SMBCLIENT
107+
if (stream->scheme == VFS_SCHEME_SMB)
108+
return retro_vfs_file_error_smb(stream);
109+
#endif
110+
97111
return ferror(stream->fp);
98112
}
99113

@@ -117,7 +131,13 @@ int64_t retro_vfs_file_tell_impl(libretro_vfs_implementation_file* stream)
117131
return -1;
118132

119133
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
134+
{
135+
#ifdef HAVE_SMBCLIENT
136+
if (stream->scheme == VFS_SCHEME_SMB)
137+
return retro_vfs_file_tell_smb(stream);
138+
#endif
120139
return _ftelli64(stream->fp);
140+
}
121141
if (lseek(stream->fd, 0, SEEK_CUR) < 0)
122142
return -1;
123143

@@ -132,7 +152,13 @@ int64_t retro_vfs_file_seek_internal(
132152
return -1;
133153

134154
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
155+
{
156+
#ifdef HAVE_SMBCLIENT
157+
if (stream->scheme == VFS_SCHEME_SMB)
158+
return retro_vfs_file_seek_smb(stream, offset, whence);
159+
#endif
135160
return _fseeki64(stream->fp, offset, whence);
161+
}
136162
if (lseek(stream->fd, (off_t)offset, whence) < 0)
137163
return -1;
138164

@@ -148,25 +174,51 @@ int64_t retro_vfs_file_seek_impl(libretro_vfs_implementation_file* stream,
148174
int64_t retro_vfs_file_read_impl(libretro_vfs_implementation_file* stream,
149175
void* s, uint64_t len)
150176
{
151-
if (!stream || (!stream->fp && stream->fh == INVALID_HANDLE_VALUE) || !s)
152-
return -1;
177+
if (!stream)
178+
return -1;
153179

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-
}
180+
#ifdef HAVE_SMBCLIENT
181+
if (stream->scheme == VFS_SCHEME_SMB)
182+
return retro_vfs_file_read_smb(stream, s, len);
183+
#endif
184+
185+
if ((!stream->fp && stream->fh == INVALID_HANDLE_VALUE) || !s)
186+
return -1;
187+
188+
if (stream->fh != INVALID_HANDLE_VALUE)
189+
{
190+
DWORD _bytes_read;
191+
ReadFile(stream->fh, (char*)s, len, &_bytes_read, NULL);
192+
return (int64_t)_bytes_read;
193+
}
160194

161195
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
162-
return fread(s, 1, (size_t)len, stream->fp);
196+
return fread(s, 1, (size_t)len, stream->fp);
163197
return read(stream->fd, s, (size_t)len);
164198
}
165199

166200

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

172224
if (stream->fh != INVALID_HANDLE_VALUE)
@@ -237,6 +289,9 @@ libretro_vfs_implementation_file* retro_vfs_file_open_impl(
237289
stream->mapsize = 0;
238290
stream->mapped = NULL;
239291
stream->scheme = VFS_SCHEME_NONE;
292+
#ifdef HAVE_SMBCLIENT
293+
stream->smb_fh = 0;
294+
#endif
240295

241296
#ifdef VFS_FRONTEND
242297
if ( path
@@ -253,6 +308,20 @@ libretro_vfs_implementation_file* retro_vfs_file_open_impl(
253308
path += sizeof("vfsonly://")-1;
254309
#endif
255310

311+
#ifdef HAVE_SMBCLIENT
312+
if ( path
313+
&& path[0] == 's'
314+
&& path[1] == 'm'
315+
&& path[2] == 'b'
316+
&& path[3] == ':'
317+
&& path[4] == '/'
318+
&& path[5] == '/'
319+
&& path[6] != '\0')
320+
{
321+
stream->scheme = VFS_SCHEME_SMB;
322+
}
323+
#endif
324+
256325
path_wide = utf8_to_utf16_string_alloc(path);
257326
windowsize_path(path_wide);
258327
path_wstring = path_wide;
@@ -317,6 +386,16 @@ libretro_vfs_implementation_file* retro_vfs_file_open_impl(
317386
? OPEN_ALWAYS
318387
: CREATE_ALWAYS;
319388

389+
#ifdef HAVE_SMBCLIENT
390+
if (stream->scheme == VFS_SCHEME_SMB)
391+
{
392+
if (!retro_vfs_file_open_smb(stream, path, mode, hints))
393+
goto error;
394+
395+
return stream;
396+
}
397+
#endif
398+
320399
if ((file_handle = CreateFile2FromAppW(path_wstring.data(), desireAccess,
321400
FILE_SHARE_READ, creationDisposition, NULL)) == INVALID_HANDLE_VALUE)
322401
goto error;
@@ -631,6 +710,10 @@ struct libretro_vfs_implementation_dir
631710
HANDLE directory;
632711
bool next;
633712
char path[PATH_MAX_LENGTH];
713+
#ifdef HAVE_SMBCLIENT
714+
intptr_t smb_directory;
715+
char smb_path[PATH_MAX_LENGTH];
716+
#endif
634717
};
635718

636719
libretro_vfs_implementation_dir* retro_vfs_opendir_impl(
@@ -653,6 +736,23 @@ libretro_vfs_implementation_dir* retro_vfs_opendir_impl(
653736

654737
_len = strlcpy(path_buf, name, sizeof(path_buf));
655738

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

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

@@ -691,6 +808,10 @@ bool retro_vfs_readdir_impl(libretro_vfs_implementation_dir* rdir)
691808

692809
const char* retro_vfs_dirent_get_name_impl(libretro_vfs_implementation_dir* rdir)
693810
{
811+
#ifdef HAVE_SMBCLIENT
812+
if (rdir && rdir->smb_directory != 0)
813+
return rdir->smb_path;
814+
#endif
694815
char* name = utf16_to_utf8_string_alloc(rdir->entry.cFileName);
695816
memset(rdir->entry.cFileName, 0, sizeof(rdir->entry.cFileName));
696817
strlcpy((char*)rdir->entry.cFileName, name, sizeof(rdir->entry.cFileName));
@@ -701,6 +822,22 @@ const char* retro_vfs_dirent_get_name_impl(libretro_vfs_implementation_dir* rdir
701822

702823
bool retro_vfs_dirent_is_dir_impl(libretro_vfs_implementation_dir* rdir)
703824
{
825+
#ifdef HAVE_SMBCLIENT
826+
if (rdir && rdir->smb_directory != 0)
827+
{
828+
char full[PATH_MAX_LENGTH];
829+
const char *name = retro_vfs_dirent_get_name_impl(rdir);
830+
831+
if (!name)
832+
return false;
833+
834+
fill_pathname_join_special(full, rdir->orig_path, name, sizeof(full));
835+
int32_t sz = 0;
836+
int st = retro_vfs_stat_smb(full, &sz);
837+
838+
return (st & RETRO_VFS_STAT_IS_DIRECTORY) != 0;
839+
}
840+
#endif
704841
const WIN32_FIND_DATA* entry = (const WIN32_FIND_DATA*)&rdir->entry;
705842
return entry->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
706843
}
@@ -710,7 +847,15 @@ int retro_vfs_closedir_impl(libretro_vfs_implementation_dir* rdir)
710847
if (!rdir)
711848
return -1;
712849

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

716861
if (rdir->orig_path)

0 commit comments

Comments
 (0)