Skip to content

Commit ea33f7d

Browse files
committed
Add SMB implemantation to UWP
1 parent dbebaf7 commit ea33f7d

File tree

1 file changed

+157
-10
lines changed

1 file changed

+157
-10
lines changed

libretro-common/vfs/vfs_implementation_uwp.cpp

Lines changed: 157 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@
5353
#include <uwp/uwp_async.h>
5454
#include <uwp/std_filesystem_compat.h>
5555

56+
#ifdef HAVE_SMBCLIENT
57+
#include "vfs_implementation_smb.h"
58+
#endif
59+
60+
5661
namespace
5762
{
5863
/* UWP deals with paths containing / instead of
@@ -90,6 +95,9 @@ struct libretro_vfs_implementation_file
9095
int fd;
9196
unsigned hints;
9297
enum vfs_scheme scheme;
98+
#ifdef HAVE_SMBCLIENT
99+
intptr_t smb_fh;
100+
#endif
93101
};
94102

95103
#define RFILE_HINT_UNBUFFERED (1 << 8)
@@ -99,6 +107,13 @@ int retro_vfs_file_close_impl(libretro_vfs_implementation_file* stream)
99107
if (!stream)
100108
return -1;
101109

110+
#ifdef HAVE_SMBCLIENT
111+
if (stream->scheme == VFS_SCHEME_SMB)
112+
{
113+
retro_vfs_file_close_smb(stream);
114+
}
115+
#endif
116+
102117
if (stream->fp)
103118
fclose(stream->fp);
104119

@@ -117,6 +132,11 @@ int retro_vfs_file_close_impl(libretro_vfs_implementation_file* stream)
117132

118133
int retro_vfs_file_error_impl(libretro_vfs_implementation_file* stream)
119134
{
135+
#ifdef HAVE_SMBCLIENT
136+
if (stream->scheme == VFS_SCHEME_SMB)
137+
return retro_vfs_file_error_smb(stream);
138+
#endif
139+
120140
return ferror(stream->fp);
121141
}
122142

@@ -140,7 +160,13 @@ int64_t retro_vfs_file_tell_impl(libretro_vfs_implementation_file* stream)
140160
return -1;
141161

142162
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
163+
{
164+
#ifdef HAVE_SMBCLIENT
165+
if (stream->scheme == VFS_SCHEME_SMB)
166+
return retro_vfs_file_tell_smb(stream);
167+
#endif
143168
return _ftelli64(stream->fp);
169+
}
144170
if (lseek(stream->fd, 0, SEEK_CUR) < 0)
145171
return -1;
146172

@@ -155,7 +181,13 @@ int64_t retro_vfs_file_seek_internal(
155181
return -1;
156182

157183
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
184+
{
185+
#ifdef HAVE_SMBCLIENT
186+
if (stream->scheme == VFS_SCHEME_SMB)
187+
return retro_vfs_file_seek_smb(stream, offset, whence);
188+
#endif
158189
return _fseeki64(stream->fp, offset, whence);
190+
}
159191
if (lseek(stream->fd, (off_t)offset, whence) < 0)
160192
return -1;
161193

@@ -171,25 +203,51 @@ int64_t retro_vfs_file_seek_impl(libretro_vfs_implementation_file* stream,
171203
int64_t retro_vfs_file_read_impl(libretro_vfs_implementation_file* stream,
172204
void* s, uint64_t len)
173205
{
174-
if (!stream || (!stream->fp && stream->fh == INVALID_HANDLE_VALUE) || !s)
175-
return -1;
206+
if (!stream)
207+
return -1;
176208

177-
if (stream->fh != INVALID_HANDLE_VALUE)
178-
{
179-
DWORD _bytes_read;
180-
ReadFile(stream->fh, (char*)s, len, &_bytes_read, NULL);
181-
return (int64_t)_bytes_read;
182-
}
209+
#ifdef HAVE_SMBCLIENT
210+
if (stream->scheme == VFS_SCHEME_SMB)
211+
return retro_vfs_file_read_smb(stream, s, len);
212+
#endif
213+
214+
if ((!stream->fp && stream->fh == INVALID_HANDLE_VALUE) || !s)
215+
return -1;
216+
217+
if (stream->fh != INVALID_HANDLE_VALUE)
218+
{
219+
DWORD _bytes_read;
220+
ReadFile(stream->fh, (char*)s, len, &_bytes_read, NULL);
221+
return (int64_t)_bytes_read;
222+
}
183223

184224
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
185-
return fread(s, 1, (size_t)len, stream->fp);
225+
return fread(s, 1, (size_t)len, stream->fp);
186226
return read(stream->fd, s, (size_t)len);
187227
}
188228

189229

190230
int64_t retro_vfs_file_write_impl(libretro_vfs_implementation_file* stream, const void* s, uint64_t len)
191231
{
192-
if (!stream || (!stream->fp && stream->fh == INVALID_HANDLE_VALUE) || !s)
232+
if (!stream)
233+
return -1;
234+
235+
#ifdef HAVE_SMBCLIENT
236+
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0 &&
237+
stream->scheme == VFS_SCHEME_SMB)
238+
{
239+
int64_t pos = 0;
240+
ssize_t ret = -1;
241+
242+
pos = retro_vfs_file_tell_smb(stream);
243+
ret = retro_vfs_file_write_smb(stream, s, len);
244+
if (ret != -1 && pos + ret > stream->size)
245+
stream->size = pos + ret;
246+
return ret;
247+
}
248+
#endif
249+
250+
if ((!stream->fp && stream->fh == INVALID_HANDLE_VALUE) || !s)
193251
return -1;
194252

195253
if (stream->fh != INVALID_HANDLE_VALUE)
@@ -276,6 +334,20 @@ libretro_vfs_implementation_file* retro_vfs_file_open_impl(
276334
path += sizeof("vfsonly://")-1;
277335
#endif
278336

337+
#ifdef HAVE_SMBCLIENT
338+
if ( path
339+
&& path[0] == 's'
340+
&& path[1] == 'm'
341+
&& path[2] == 'b'
342+
&& path[3] == ':'
343+
&& path[4] == '/'
344+
&& path[5] == '/'
345+
&& path[6] != '\0')
346+
{
347+
stream->scheme = VFS_SCHEME_SMB;
348+
}
349+
#endif
350+
279351
path_wide = utf8_to_utf16_string_alloc(path);
280352
windowsize_path(path_wide);
281353
path_wstring = path_wide;
@@ -340,6 +412,16 @@ libretro_vfs_implementation_file* retro_vfs_file_open_impl(
340412
? OPEN_ALWAYS
341413
: CREATE_ALWAYS;
342414

415+
#ifdef HAVE_SMBCLIENT
416+
if (stream->scheme == VFS_SCHEME_SMB)
417+
{
418+
if (!retro_vfs_file_open_smb(stream, path, mode, hints))
419+
goto error;
420+
421+
return stream;
422+
}
423+
#endif
424+
343425
if ((file_handle = CreateFile2FromAppW(path_wstring.data(), desireAccess,
344426
FILE_SHARE_READ, creationDisposition, NULL)) == INVALID_HANDLE_VALUE)
345427
goto error;
@@ -654,6 +736,10 @@ struct libretro_vfs_implementation_dir
654736
HANDLE directory;
655737
bool next;
656738
char path[PATH_MAX_LENGTH];
739+
#ifdef HAVE_SMBCLIENT
740+
intptr_t smb_directory;
741+
char smb_path[PATH_MAX_LENGTH];
742+
#endif
657743
};
658744

659745
libretro_vfs_implementation_dir* retro_vfs_opendir_impl(
@@ -676,6 +762,23 @@ libretro_vfs_implementation_dir* retro_vfs_opendir_impl(
676762

677763
_len = strlcpy(path_buf, name, sizeof(path_buf));
678764

765+
#ifdef HAVE_SMBCLIENT
766+
if (name[0]=='s' && name[1]=='m' && name[2]=='b' &&
767+
name[3]==':' && name[4]=='/' && name[5]=='/' && name[6] != '\0')
768+
{
769+
intptr_t dh = retro_vfs_opendir_smb(name, include_hidden);
770+
if (dh < 0)
771+
{
772+
free(rdir->orig_path);
773+
free(rdir);
774+
return NULL;
775+
}
776+
rdir->smb_directory = dh;
777+
rdir->smb_path[0] = '\0';
778+
return rdir;
779+
}
780+
#endif
781+
679782
/* Non-NT platforms don't like extra slashes in the path */
680783
if (path_buf[_len - 1] != '\\')
681784
path_buf[_len++] = '\\';
@@ -705,6 +808,22 @@ libretro_vfs_implementation_dir* retro_vfs_opendir_impl(
705808

706809
bool retro_vfs_readdir_impl(libretro_vfs_implementation_dir* rdir)
707810
{
811+
#ifdef HAVE_SMBCLIENT
812+
if (rdir->smb_directory != 0)
813+
{
814+
struct smbc_dirent *de = retro_vfs_readdir_smb(rdir->smb_directory);
815+
if (!de)
816+
return false;
817+
strlcpy(rdir->smb_path, de->name, sizeof(rdir->smb_path));
818+
return true;
819+
}
820+
/* If we opened an SMB path but failed, do not fall through to native readdir */
821+
if (rdir->orig_path &&
822+
rdir->orig_path[0]=='s' && rdir->orig_path[1]=='m' && rdir->orig_path[2]=='b' &&
823+
rdir->orig_path[3]==':' && rdir->orig_path[4]=='/' && rdir->orig_path[5]=='/' )
824+
return false;
825+
#endif
826+
708827
if (rdir->next)
709828
return (FindNextFileW(rdir->directory, &rdir->entry) != 0);
710829

@@ -714,6 +833,10 @@ bool retro_vfs_readdir_impl(libretro_vfs_implementation_dir* rdir)
714833

715834
const char* retro_vfs_dirent_get_name_impl(libretro_vfs_implementation_dir* rdir)
716835
{
836+
#ifdef HAVE_SMBCLIENT
837+
if (rdir->smb_directory != 0)
838+
return rdir->smb_path;
839+
#endif
717840
char* name = utf16_to_utf8_string_alloc(rdir->entry.cFileName);
718841
memset(rdir->entry.cFileName, 0, sizeof(rdir->entry.cFileName));
719842
strlcpy((char*)rdir->entry.cFileName, name, sizeof(rdir->entry.cFileName));
@@ -724,6 +847,22 @@ const char* retro_vfs_dirent_get_name_impl(libretro_vfs_implementation_dir* rdir
724847

725848
bool retro_vfs_dirent_is_dir_impl(libretro_vfs_implementation_dir* rdir)
726849
{
850+
#ifdef HAVE_SMBCLIENT
851+
if (rdir->smb_directory != 0)
852+
{
853+
char full[PATH_MAX_LENGTH];
854+
const char *name = retro_vfs_dirent_get_name_impl(rdir);
855+
856+
if (!name)
857+
return false;
858+
859+
fill_pathname_join_special(full, rdir->orig_path, name, sizeof(full));
860+
int32_t sz = 0;
861+
int st = retro_vfs_stat_smb(full, &sz);
862+
863+
return (st & RETRO_VFS_STAT_IS_DIRECTORY) != 0;
864+
}
865+
#endif
727866
const WIN32_FIND_DATA* entry = (const WIN32_FIND_DATA*)&rdir->entry;
728867
return entry->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
729868
}
@@ -733,6 +872,14 @@ int retro_vfs_closedir_impl(libretro_vfs_implementation_dir* rdir)
733872
if (!rdir)
734873
return -1;
735874

875+
#ifdef HAVE_SMBCLIENT
876+
if (rdir->smb_directory != 0)
877+
{
878+
retro_vfs_closedir_smb(rdir->smb_directory);
879+
rdir->smb_directory = 0;
880+
}
881+
#endif
882+
736883
if (rdir->directory != INVALID_HANDLE_VALUE)
737884
FindClose(rdir->directory);
738885

0 commit comments

Comments
 (0)