Skip to content

Commit 49d49e3

Browse files
committed
Add SMB implementation to UWP
1 parent 6e30e0b commit 49d49e3

File tree

1 file changed

+159
-10
lines changed

1 file changed

+159
-10
lines changed

libretro-common/vfs/vfs_implementation_uwp.cpp

Lines changed: 159 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@
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+
5660
namespace
5761
{
5862
/* UWP deals with paths containing / instead of
@@ -90,6 +94,9 @@ struct libretro_vfs_implementation_file
9094
int fd;
9195
unsigned hints;
9296
enum vfs_scheme scheme;
97+
#ifdef HAVE_SMBCLIENT
98+
intptr_t smb_fh;
99+
#endif
93100
};
94101

95102
#define RFILE_HINT_UNBUFFERED (1 << 8)
@@ -99,6 +106,13 @@ int retro_vfs_file_close_impl(libretro_vfs_implementation_file* stream)
99106
if (!stream)
100107
return -1;
101108

109+
#ifdef HAVE_SMBCLIENT
110+
if (stream->scheme == VFS_SCHEME_SMB)
111+
{
112+
retro_vfs_file_close_smb(stream);
113+
}
114+
#endif
115+
102116
if (stream->fp)
103117
fclose(stream->fp);
104118

@@ -117,6 +131,11 @@ int retro_vfs_file_close_impl(libretro_vfs_implementation_file* stream)
117131

118132
int retro_vfs_file_error_impl(libretro_vfs_implementation_file* stream)
119133
{
134+
#ifdef HAVE_SMBCLIENT
135+
if (stream->scheme == VFS_SCHEME_SMB)
136+
return retro_vfs_file_error_smb(stream);
137+
#endif
138+
120139
return ferror(stream->fp);
121140
}
122141

@@ -140,7 +159,13 @@ int64_t retro_vfs_file_tell_impl(libretro_vfs_implementation_file* stream)
140159
return -1;
141160

142161
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
162+
{
163+
#ifdef HAVE_SMBCLIENT
164+
if (stream->scheme == VFS_SCHEME_SMB)
165+
return retro_vfs_file_tell_smb(stream);
166+
#endif
143167
return _ftelli64(stream->fp);
168+
}
144169
if (lseek(stream->fd, 0, SEEK_CUR) < 0)
145170
return -1;
146171

@@ -155,7 +180,13 @@ int64_t retro_vfs_file_seek_internal(
155180
return -1;
156181

157182
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
183+
{
184+
#ifdef HAVE_SMBCLIENT
185+
if (stream->scheme == VFS_SCHEME_SMB)
186+
return retro_vfs_file_seek_smb(stream, offset, whence);
187+
#endif
158188
return _fseeki64(stream->fp, offset, whence);
189+
}
159190
if (lseek(stream->fd, (off_t)offset, whence) < 0)
160191
return -1;
161192

@@ -171,25 +202,51 @@ int64_t retro_vfs_file_seek_impl(libretro_vfs_implementation_file* stream,
171202
int64_t retro_vfs_file_read_impl(libretro_vfs_implementation_file* stream,
172203
void* s, uint64_t len)
173204
{
174-
if (!stream || (!stream->fp && stream->fh == INVALID_HANDLE_VALUE) || !s)
175-
return -1;
205+
if (!stream)
206+
return -1;
176207

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-
}
208+
#ifdef HAVE_SMBCLIENT
209+
if (stream->scheme == VFS_SCHEME_SMB)
210+
return retro_vfs_file_read_smb(stream, s, len);
211+
#endif
212+
213+
if ((!stream->fp && stream->fh == INVALID_HANDLE_VALUE) || !s)
214+
return -1;
215+
216+
if (stream->fh != INVALID_HANDLE_VALUE)
217+
{
218+
DWORD _bytes_read;
219+
ReadFile(stream->fh, (char*)s, len, &_bytes_read, NULL);
220+
return (int64_t)_bytes_read;
221+
}
183222

184223
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
185-
return fread(s, 1, (size_t)len, stream->fp);
224+
return fread(s, 1, (size_t)len, stream->fp);
186225
return read(stream->fd, s, (size_t)len);
187226
}
188227

189228

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

195252
if (stream->fh != INVALID_HANDLE_VALUE)
@@ -260,6 +317,9 @@ libretro_vfs_implementation_file* retro_vfs_file_open_impl(
260317
stream->mapsize = 0;
261318
stream->mapped = NULL;
262319
stream->scheme = VFS_SCHEME_NONE;
320+
#ifdef HAVE_SMBCLIENT
321+
stream->smb_fh = 0;
322+
#endif
263323

264324
#ifdef VFS_FRONTEND
265325
if ( path
@@ -276,6 +336,20 @@ libretro_vfs_implementation_file* retro_vfs_file_open_impl(
276336
path += sizeof("vfsonly://")-1;
277337
#endif
278338

339+
#ifdef HAVE_SMBCLIENT
340+
if ( path
341+
&& path[0] == 's'
342+
&& path[1] == 'm'
343+
&& path[2] == 'b'
344+
&& path[3] == ':'
345+
&& path[4] == '/'
346+
&& path[5] == '/'
347+
&& path[6] != '\0')
348+
{
349+
stream->scheme = VFS_SCHEME_SMB;
350+
}
351+
#endif
352+
279353
path_wide = utf8_to_utf16_string_alloc(path);
280354
windowsize_path(path_wide);
281355
path_wstring = path_wide;
@@ -340,6 +414,16 @@ libretro_vfs_implementation_file* retro_vfs_file_open_impl(
340414
? OPEN_ALWAYS
341415
: CREATE_ALWAYS;
342416

417+
#ifdef HAVE_SMBCLIENT
418+
if (stream->scheme == VFS_SCHEME_SMB)
419+
{
420+
if (!retro_vfs_file_open_smb(stream, path, mode, hints))
421+
goto error;
422+
423+
return stream;
424+
}
425+
#endif
426+
343427
if ((file_handle = CreateFile2FromAppW(path_wstring.data(), desireAccess,
344428
FILE_SHARE_READ, creationDisposition, NULL)) == INVALID_HANDLE_VALUE)
345429
goto error;
@@ -654,6 +738,10 @@ struct libretro_vfs_implementation_dir
654738
HANDLE directory;
655739
bool next;
656740
char path[PATH_MAX_LENGTH];
741+
#ifdef HAVE_SMBCLIENT
742+
intptr_t smb_directory;
743+
char smb_path[PATH_MAX_LENGTH];
744+
#endif
657745
};
658746

659747
libretro_vfs_implementation_dir* retro_vfs_opendir_impl(
@@ -676,6 +764,23 @@ libretro_vfs_implementation_dir* retro_vfs_opendir_impl(
676764

677765
_len = strlcpy(path_buf, name, sizeof(path_buf));
678766

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

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

@@ -714,6 +835,10 @@ bool retro_vfs_readdir_impl(libretro_vfs_implementation_dir* rdir)
714835

715836
const char* retro_vfs_dirent_get_name_impl(libretro_vfs_implementation_dir* rdir)
716837
{
838+
#ifdef HAVE_SMBCLIENT
839+
if (rdir->smb_directory != 0)
840+
return rdir->smb_path;
841+
#endif
717842
char* name = utf16_to_utf8_string_alloc(rdir->entry.cFileName);
718843
memset(rdir->entry.cFileName, 0, sizeof(rdir->entry.cFileName));
719844
strlcpy((char*)rdir->entry.cFileName, name, sizeof(rdir->entry.cFileName));
@@ -724,6 +849,22 @@ const char* retro_vfs_dirent_get_name_impl(libretro_vfs_implementation_dir* rdir
724849

725850
bool retro_vfs_dirent_is_dir_impl(libretro_vfs_implementation_dir* rdir)
726851
{
852+
#ifdef HAVE_SMBCLIENT
853+
if (rdir->smb_directory != 0)
854+
{
855+
char full[PATH_MAX_LENGTH];
856+
const char *name = retro_vfs_dirent_get_name_impl(rdir);
857+
858+
if (!name)
859+
return false;
860+
861+
fill_pathname_join_special(full, rdir->orig_path, name, sizeof(full));
862+
int32_t sz = 0;
863+
int st = retro_vfs_stat_smb(full, &sz);
864+
865+
return (st & RETRO_VFS_STAT_IS_DIRECTORY) != 0;
866+
}
867+
#endif
727868
const WIN32_FIND_DATA* entry = (const WIN32_FIND_DATA*)&rdir->entry;
728869
return entry->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
729870
}
@@ -733,6 +874,14 @@ int retro_vfs_closedir_impl(libretro_vfs_implementation_dir* rdir)
733874
if (!rdir)
734875
return -1;
735876

877+
#ifdef HAVE_SMBCLIENT
878+
if (rdir->smb_directory != 0)
879+
{
880+
retro_vfs_closedir_smb(rdir->smb_directory);
881+
rdir->smb_directory = 0;
882+
}
883+
#endif
884+
736885
if (rdir->directory != INVALID_HANDLE_VALUE)
737886
FindClose(rdir->directory);
738887

0 commit comments

Comments
 (0)