From 181ff3f2bff1cba8b67a800bbf3ef3607cffe8e6 Mon Sep 17 00:00:00 2001 From: ITotalJustice <47043333+ITotalJustice@users.noreply.github.com> Date: Thu, 4 Sep 2025 12:18:34 +0100 Subject: [PATCH] devoptab: fix http config parsing, add more options to network mounts (timeout,uid,port). fs: update path size. fs path was changed to 255 in the past because that is the real path size that fs can handle. however, this restriction does not apply to nfs, samba, http - and it is very easy to exceed this 255 path length. to fix this, i have increased the path len to 1024. this allows fs to continue to work as the buffer is big enough, but also gives network mounts enough space to work with. --- sphaira/include/fs.hpp | 11 +++- sphaira/include/swkbd.hpp | 5 +- sphaira/include/ui/sidebar.hpp | 3 +- sphaira/source/option.cpp | 2 +- sphaira/source/swkbd.cpp | 2 +- sphaira/source/utils/devoptab_bfsar.cpp | 6 +- sphaira/source/utils/devoptab_http.cpp | 45 ++++++++++----- sphaira/source/utils/devoptab_nca.cpp | 6 +- sphaira/source/utils/devoptab_nfs.cpp | 74 +++++++++++++++++++------ sphaira/source/utils/devoptab_nro.cpp | 6 +- sphaira/source/utils/devoptab_nsp.cpp | 6 +- sphaira/source/utils/devoptab_save.cpp | 6 +- sphaira/source/utils/devoptab_smb2.cpp | 47 +++++++++++----- sphaira/source/utils/devoptab_xci.cpp | 6 +- sphaira/source/utils/devoptab_zip.cpp | 6 +- sphaira/source/web.cpp | 4 -- 16 files changed, 156 insertions(+), 79 deletions(-) diff --git a/sphaira/include/fs.hpp b/sphaira/include/fs.hpp index 6ba086b..5b7f75c 100644 --- a/sphaira/include/fs.hpp +++ b/sphaira/include/fs.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "defines.hpp" namespace fs { @@ -168,7 +169,7 @@ struct FsPath { return path[0] == str[0]; } - char s[FS_MAX_PATH]{}; + char s[PATH_MAX]{}; }; inline FsPath operator+(const char* v, const FsPath& fp) { @@ -187,8 +188,12 @@ inline FsPath operator+(const std::string_view& v, const FsPath& fp) { } // Fs seems to be limted to file paths of 255 characters. +// i've disabled this as network mounts will often have very long paths +// that do not have this limit. +// a proper fix would be to return an error if the path is too long and the path +// is native. struct FsPathReal { - static constexpr inline size_t FS_REAL_MAX_LENGTH = 255; + static constexpr inline size_t FS_REAL_MAX_LENGTH = PATH_MAX; constexpr FsPathReal(const FsPath& str) : FsPathReal{str.s} { } explicit constexpr FsPathReal(const char* str) { @@ -215,7 +220,7 @@ struct FsPathReal { constexpr operator const char*() const { return s; } constexpr operator std::string_view() const { return s; } - char s[FS_MAX_PATH]; + char s[PATH_MAX]; }; // fwd diff --git a/sphaira/include/swkbd.hpp b/sphaira/include/swkbd.hpp index 346204c..0255292 100644 --- a/sphaira/include/swkbd.hpp +++ b/sphaira/include/swkbd.hpp @@ -2,10 +2,11 @@ #include #include +#include namespace sphaira::swkbd { -Result ShowText(std::string& out, const char* guide = nullptr, const char* initial = nullptr, s64 len_min = -1, s64 len_max = FS_MAX_PATH); -Result ShowNumPad(s64& out, const char* guide = nullptr, const char* initial = nullptr, s64 len_min = -1, s64 len_max = FS_MAX_PATH); +Result ShowText(std::string& out, const char* guide = nullptr, const char* initial = nullptr, s64 len_min = -1, s64 len_max = PATH_MAX); +Result ShowNumPad(s64& out, const char* guide = nullptr, const char* initial = nullptr, s64 len_min = -1, s64 len_max = PATH_MAX); } // namespace sphaira::swkbd diff --git a/sphaira/include/ui/sidebar.hpp b/sphaira/include/ui/sidebar.hpp index 1a98a3d..60f875c 100644 --- a/sphaira/include/ui/sidebar.hpp +++ b/sphaira/include/ui/sidebar.hpp @@ -7,6 +7,7 @@ #include #include #include +#include namespace sphaira::ui { @@ -174,7 +175,7 @@ private: class SidebarEntryTextInput final : public SidebarEntryTextBase { public: - explicit SidebarEntryTextInput(const std::string& title, const std::string& value, const std::string& guide = {}, s64 len_min = -1, s64 len_max = FS_MAX_PATH, const std::string& info = ""); + explicit SidebarEntryTextInput(const std::string& title, const std::string& value, const std::string& guide = {}, s64 len_min = -1, s64 len_max = PATH_MAX, const std::string& info = ""); private: const std::string m_guide; diff --git a/sphaira/source/option.cpp b/sphaira/source/option.cpp index cec5ec0..bb77876 100644 --- a/sphaira/source/option.cpp +++ b/sphaira/source/option.cpp @@ -20,7 +20,7 @@ auto OptionBase::GetInternal(const char* name) -> T { } else if constexpr(std::is_same_v) { m_value = ini_getf(m_section.c_str(), name, m_default_value, App::CONFIG_PATH); } else if constexpr(std::is_same_v) { - char buf[FS_MAX_PATH]; + char buf[PATH_MAX]{}; ini_gets(m_section.c_str(), name, m_default_value.c_str(), buf, sizeof(buf), App::CONFIG_PATH); m_value = buf; } diff --git a/sphaira/source/swkbd.cpp b/sphaira/source/swkbd.cpp index b5be771..37717ee 100644 --- a/sphaira/source/swkbd.cpp +++ b/sphaira/source/swkbd.cpp @@ -6,7 +6,7 @@ namespace sphaira::swkbd { namespace { struct Config { - char out_text[FS_MAX_PATH]{}; + char out_text[PATH_MAX]{}; bool numpad{}; }; diff --git a/sphaira/source/utils/devoptab_bfsar.cpp b/sphaira/source/utils/devoptab_bfsar.cpp index 1fd95d8..4bc03c7 100644 --- a/sphaira/source/utils/devoptab_bfsar.cpp +++ b/sphaira/source/utils/devoptab_bfsar.cpp @@ -92,7 +92,7 @@ int devoptab_open(struct _reent *r, void *fileStruct, const char *_path, int fla auto file = static_cast(fileStruct); std::memset(file, 0, sizeof(*file)); - char path[FS_MAX_PATH]; + char path[PATH_MAX]; if (!common::fix_path(_path, path)) { return set_errno(r, ENOENT); } @@ -161,7 +161,7 @@ DIR_ITER* devoptab_diropen(struct _reent *r, DIR_ITER *dirState, const char *_pa auto dir = static_cast(dirState->dirStruct); std::memset(dir, 0, sizeof(*dir)); - char path[FS_MAX_PATH]; + char path[PATH_MAX]; if (!common::fix_path(_path, path)) { set_errno(r, ENOENT); return NULL; @@ -244,7 +244,7 @@ int devoptab_dirclose(struct _reent *r, DIR_ITER *dirState) { int devoptab_lstat(struct _reent *r, const char *_path, struct stat *st) { auto device = (Device*)r->deviceData; - char path[FS_MAX_PATH]; + char path[PATH_MAX]; if (!common::fix_path(_path, path)) { return set_errno(r, ENOENT); } diff --git a/sphaira/source/utils/devoptab_http.cpp b/sphaira/source/utils/devoptab_http.cpp index e6edb69..05c58cf 100644 --- a/sphaira/source/utils/devoptab_http.cpp +++ b/sphaira/source/utils/devoptab_http.cpp @@ -13,11 +13,14 @@ #include #include #include +#include #include namespace sphaira::devoptab { namespace { +constexpr int DEFAULT_HTTP_TIMEOUT = 3000; // 3 seconds. + #define CURL_EASY_SETOPT_LOG(handle, opt, v) \ if (auto r = curl_easy_setopt(handle, opt, v); r != CURLE_OK) { \ log_write("curl_easy_setopt(%s, %s) msg: %s\n", #opt, #v, curl_easy_strerror(r)); \ @@ -33,6 +36,8 @@ struct HttpMountConfig { std::string url{}; std::string user{}; std::string pass{}; + std::optional port{}; + int timeout{DEFAULT_HTTP_TIMEOUT}; }; using HttpMountConfigs = std::vector; @@ -128,9 +133,8 @@ std::string build_url(const std::string& base, const std::string& path, bool is_ void http_set_common_options(Device& client, const std::string& url) { curl_easy_reset(client.curl); CURL_EASY_SETOPT_LOG(client.curl, CURLOPT_URL, url.c_str()); - // todo: make the timeouts configurable. - CURL_EASY_SETOPT_LOG(client.curl, CURLOPT_TIMEOUT, 5L); - CURL_EASY_SETOPT_LOG(client.curl, CURLOPT_CONNECTTIMEOUT, 5L); + CURL_EASY_SETOPT_LOG(client.curl, CURLOPT_TIMEOUT, (long)client.config.timeout); + CURL_EASY_SETOPT_LOG(client.curl, CURLOPT_CONNECTTIMEOUT, (long)client.config.timeout); CURL_EASY_SETOPT_LOG(client.curl, CURLOPT_AUTOREFERER, 1L); CURL_EASY_SETOPT_LOG(client.curl, CURLOPT_FOLLOWLOCATION, 1L); CURL_EASY_SETOPT_LOG(client.curl, CURLOPT_SSL_VERIFYPEER, 0L); @@ -140,6 +144,10 @@ void http_set_common_options(Device& client, const std::string& url) { CURL_EASY_SETOPT_LOG(client.curl, CURLOPT_NOPROGRESS, 0L); CURL_EASY_SETOPT_LOG(client.curl, CURLOPT_BUFFERSIZE, 1024L * 512L); + if (client.config.port) { + CURL_EASY_SETOPT_LOG(client.curl, CURLOPT_PORT, (long)client.config.port.value()); + } + // enable all forms of compression supported by libcurl. CURL_EASY_SETOPT_LOG(client.curl, CURLOPT_ACCEPT_ENCODING, ""); @@ -345,10 +353,11 @@ int devoptab_open(struct _reent *r, void *fileStruct, const char *_path, int fla // todo: add this check to all devoptabs. if ((flags & O_ACCMODE) != O_RDONLY) { + log_write("[HTTP] Only read-only mode is supported\n"); return set_errno(r, EINVAL); } - char path[FS_MAX_PATH]{}; + char path[PATH_MAX]{}; if (!common::fix_path(_path, path)) { return set_errno(r, ENOENT); } @@ -359,10 +368,12 @@ int devoptab_open(struct _reent *r, void *fileStruct, const char *_path, int fla struct stat st; if (!http_stat(*device, path, &st, false)) { + log_write("[HTTP] http_stat() failed for file: %s\n", path); return set_errno(r, ENOENT); } if (st.st_mode & S_IFDIR) { + log_write("[HTTP] Attempted to open a directory as a file: %s\n", path); return set_errno(r, EISDIR); } @@ -425,7 +436,7 @@ DIR_ITER* devoptab_diropen(struct _reent *r, DIR_ITER *dirState, const char *_pa std::memset(dir, 0, sizeof(*dir)); SCOPED_MUTEX(&device->mutex); - char path[FS_MAX_PATH]; + char path[PATH_MAX]; if (!common::fix_path(_path, path)) { set_errno(r, ENOENT); return NULL; @@ -493,7 +504,7 @@ int devoptab_lstat(struct _reent *r, const char *_path, struct stat *st) { auto device = (Device*)r->deviceData; SCOPED_MUTEX(&device->mutex); - char path[FS_MAX_PATH]; + char path[PATH_MAX]; if (!common::fix_path(_path, path)) { return set_errno(r, ENOENT); } @@ -559,13 +570,17 @@ Result MountHttpAll() { e->emplace_back(Section); } - HttpMountConfig config; - if (std::strcmp(Key, "url") == 0) { - config.url = Value; - } else if (std::strcmp(Key, "user") == 0) { - config.user = Value; - } else if (std::strcmp(Key, "pass") == 0) { - config.pass = Value; + if (!std::strcmp(Key, "url")) { + e->back().url = Value; + } else if (!std::strcmp(Key, "user")) { + e->back().user = Value; + } else if (!std::strcmp(Key, "pass")) { + e->back().pass = Value; + } else if (!std::strcmp(Key, "port")) { + // todo: idk what the default should be. + e->back().port = ini_parse_getl(Value, 8000); + } else if (!std::strcmp(Key, "timeout")) { + e->back().timeout = ini_parse_getl(Value, DEFAULT_HTTP_TIMEOUT); } else { log_write("[HTTP] INI: Unknown key %s=%s\n", Key, Value); } @@ -607,8 +622,8 @@ Result MountHttpAll() { entry->devoptab.name = entry->name; entry->devoptab.deviceData = &entry->device; entry->device.config = config; - std::snprintf(entry->name, sizeof(entry->name), "%s", config.name.c_str()); - std::snprintf(entry->mount, sizeof(entry->mount), "%s:/", config.name.c_str()); + std::snprintf(entry->name, sizeof(entry->name), "[HTTP] %s", config.name.c_str()); + std::snprintf(entry->mount, sizeof(entry->mount), "[HTTP] %s:/", config.name.c_str()); R_UNLESS(AddDevice(&entry->devoptab) >= 0, 0x1); log_write("[HTTP] DEVICE SUCCESS %s %s\n", entry->device.config.url.c_str(), entry->name); diff --git a/sphaira/source/utils/devoptab_nca.cpp b/sphaira/source/utils/devoptab_nca.cpp index d8f1dbc..ba98d21 100644 --- a/sphaira/source/utils/devoptab_nca.cpp +++ b/sphaira/source/utils/devoptab_nca.cpp @@ -164,7 +164,7 @@ int devoptab_open(struct _reent *r, void *fileStruct, const char *_path, int fla auto file = static_cast(fileStruct); std::memset(file, 0, sizeof(*file)); - char path[FS_MAX_PATH]; + char path[PATH_MAX]; if (!common::fix_path(_path, path)) { return set_errno(r, ENOENT); } @@ -232,7 +232,7 @@ DIR_ITER* devoptab_diropen(struct _reent *r, DIR_ITER *dirState, const char *_pa auto dir = static_cast(dirState->dirStruct); std::memset(dir, 0, sizeof(*dir)); - char path[FS_MAX_PATH]; + char path[PATH_MAX]; if (!common::fix_path(_path, path)) { set_errno(r, ENOENT); return NULL; @@ -320,7 +320,7 @@ int devoptab_dirclose(struct _reent *r, DIR_ITER *dirState) { int devoptab_lstat(struct _reent *r, const char *_path, struct stat *st) { auto device = (Device*)r->deviceData; - char path[FS_MAX_PATH]; + char path[PATH_MAX]; if (!common::fix_path(_path, path)) { return set_errno(r, ENOENT); } diff --git a/sphaira/source/utils/devoptab_nfs.cpp b/sphaira/source/utils/devoptab_nfs.cpp index e936b52..7b32a89 100644 --- a/sphaira/source/utils/devoptab_nfs.cpp +++ b/sphaira/source/utils/devoptab_nfs.cpp @@ -15,16 +15,25 @@ namespace sphaira::devoptab { namespace { +constexpr int DEFAULT_NFS_UID = 0; +constexpr int DEFAULT_NFS_GID = 0; +constexpr int DEFAULT_NFS_VERSION = 3; +constexpr int DEFAULT_NFS_TIMEOUT = 3000; // 3 seconds. + struct NfsMountConfig { std::string name{}; std::string url{}; - std::string path{}; + int uid{DEFAULT_NFS_UID}; + int gid{DEFAULT_NFS_GID}; + int version{DEFAULT_NFS_VERSION}; + int timeout{DEFAULT_NFS_TIMEOUT}; bool read_only{}; }; using NfsMountConfigs = std::vector; struct Device { nfs_context* nfs{}; + nfs_url* url{}; NfsMountConfig config; bool mounted{}; Mutex mutex{}; @@ -51,9 +60,31 @@ bool mount_nfs(Device& device) { log_write("[NFS] nfs_init_context() failed\n"); return false; } + + nfs_set_uid(device.nfs, device.config.uid); + nfs_set_gid(device.nfs, device.config.gid); + nfs_set_version(device.nfs, device.config.version); + nfs_set_timeout(device.nfs, device.config.timeout); + nfs_set_readonly(device.nfs, device.config.read_only); + // nfs_set_mountport(device.nfs, device.url->port); } - const auto ret = nfs_mount(device.nfs, device.config.url.c_str(), device.config.path.c_str()); + // fix the url if needed. + if (!device.config.url.starts_with("nfs://")) { + log_write("[NFS] Prepending nfs:// to url: %s\n", device.config.url.c_str()); + device.config.url = "nfs://" + device.config.url; + } + + if (!device.url) { + // todo: check all parse options. + device.url = nfs_parse_url_dir(device.nfs, device.config.url.c_str()); + if (!device.url) { + log_write("[NFS] nfs_parse_url() failed for url: %s\n", device.config.url.c_str()); + return false; + } + } + + const auto ret = nfs_mount(device.nfs, device.url->server, device.url->path); if (ret) { log_write("[NFS] nfs_mount() failed: %s errno: %s\n", nfs_get_error(device.nfs), std::strerror(-ret)); return false; @@ -78,7 +109,7 @@ int devoptab_open(struct _reent *r, void *fileStruct, const char *_path, int fla return set_errno(r, EROFS); } - char path[FS_MAX_PATH]{}; + char path[PATH_MAX]{}; if (!common::fix_path(_path, path)) { return set_errno(r, ENOENT); } @@ -209,7 +240,7 @@ int devoptab_unlink(struct _reent *r, const char *_path) { auto device = static_cast(r->deviceData); SCOPED_MUTEX(&device->mutex); - char path[FS_MAX_PATH]{}; + char path[PATH_MAX]{}; if (!common::fix_path(_path, path)) { return set_errno(r, ENOENT); } @@ -231,12 +262,12 @@ int devoptab_rename(struct _reent *r, const char *_oldName, const char *_newName auto device = static_cast(r->deviceData); SCOPED_MUTEX(&device->mutex); - char oldName[FS_MAX_PATH]{}; + char oldName[PATH_MAX]{}; if (!common::fix_path(_oldName, oldName)) { return set_errno(r, ENOENT); } - char newName[FS_MAX_PATH]{}; + char newName[PATH_MAX]{}; if (!common::fix_path(_newName, newName)) { return set_errno(r, ENOENT); } @@ -258,7 +289,7 @@ int devoptab_mkdir(struct _reent *r, const char *_path, int mode) { auto device = static_cast(r->deviceData); SCOPED_MUTEX(&device->mutex); - char path[FS_MAX_PATH]{}; + char path[PATH_MAX]{}; if (!common::fix_path(_path, path)) { return set_errno(r, ENOENT); } @@ -280,7 +311,7 @@ int devoptab_rmdir(struct _reent *r, const char *_path) { auto device = static_cast(r->deviceData); SCOPED_MUTEX(&device->mutex); - char path[FS_MAX_PATH]{}; + char path[PATH_MAX]{}; if (!common::fix_path(_path, path)) { return set_errno(r, ENOENT); } @@ -304,7 +335,7 @@ DIR_ITER* devoptab_diropen(struct _reent *r, DIR_ITER *dirState, const char *_pa std::memset(dir, 0, sizeof(*dir)); SCOPED_MUTEX(&device->mutex); - char path[FS_MAX_PATH]{}; + char path[PATH_MAX]{}; if (!common::fix_path(_path, path)) { set_errno(r, ENOENT); return nullptr; @@ -380,7 +411,7 @@ int devoptab_lstat(struct _reent *r, const char *_path, struct stat *st) { auto device = static_cast(r->deviceData); SCOPED_MUTEX(&device->mutex); - char path[FS_MAX_PATH]{}; + char path[PATH_MAX]{}; if (!common::fix_path(_path, path)) { return set_errno(r, ENOENT); } @@ -415,7 +446,7 @@ int devoptab_statvfs(struct _reent *r, const char *_path, struct statvfs *buf) { auto device = static_cast(r->deviceData); SCOPED_MUTEX(&device->mutex); - char path[FS_MAX_PATH]{}; + char path[PATH_MAX]{}; if (!common::fix_path(_path, path)) { return set_errno(r, ENOENT); } @@ -455,7 +486,7 @@ int devoptab_utimes(struct _reent *r, const char *_path, const struct timeval ti return set_errno(r, EINVAL); } - char path[FS_MAX_PATH]{}; + char path[PATH_MAX]{}; if (!common::fix_path(_path, path)) { return set_errno(r, ENOENT); } @@ -514,6 +545,11 @@ struct Entry { if (device.mounted) { nfs_umount(device.nfs); } + + if (device.url) { + nfs_destroy_url(device.url); + } + nfs_destroy_context(device.nfs); } @@ -542,10 +578,16 @@ Result MountNfsAll() { if (!std::strcmp(Key, "url")) { e->back().url = Value; - } else if (!std::strcmp(Key, "path")) { - e->back().path = Value; } else if (!std::strcmp(Key, "name")) { e->back().name = Value; + } else if (!std::strcmp(Key, "uid")) { + e->back().uid = ini_parse_getl(Value, DEFAULT_NFS_UID); + } else if (!std::strcmp(Key, "gid")) { + e->back().gid = ini_parse_getl(Value, DEFAULT_NFS_GID); + } else if (!std::strcmp(Key, "version")) { + e->back().version = ini_parse_getl(Value, DEFAULT_NFS_VERSION); + } else if (!std::strcmp(Key, "timeout")) { + e->back().timeout = ini_parse_getl(Value, DEFAULT_NFS_TIMEOUT); } else if (!std::strcmp(Key, "read_only")) { e->back().read_only = ini_parse_getbool(Value, false); } else { @@ -590,8 +632,8 @@ Result MountNfsAll() { entry->devoptab.name = entry->name; entry->devoptab.deviceData = &entry->device; entry->device.config = config; - std::snprintf(entry->name, sizeof(entry->name), "%s", config.name.c_str()); - std::snprintf(entry->mount, sizeof(entry->mount), "%s:/", config.name.c_str()); + std::snprintf(entry->name, sizeof(entry->name), "[NFS] %s", config.name.c_str()); + std::snprintf(entry->mount, sizeof(entry->mount), "[NFS] %s:/", config.name.c_str()); common::update_devoptab_for_read_only(&entry->devoptab, config.read_only); R_UNLESS(AddDevice(&entry->devoptab) >= 0, 0x1); diff --git a/sphaira/source/utils/devoptab_nro.cpp b/sphaira/source/utils/devoptab_nro.cpp index 21ae28c..761b98d 100644 --- a/sphaira/source/utils/devoptab_nro.cpp +++ b/sphaira/source/utils/devoptab_nro.cpp @@ -128,7 +128,7 @@ int devoptab_open(struct _reent *r, void *fileStruct, const char *_path, int fla auto file = static_cast(fileStruct); std::memset(file, 0, sizeof(*file)); - char path[FS_MAX_PATH]; + char path[PATH_MAX]; if (!common::fix_path(_path, path)) { return set_errno(r, ENOENT); } @@ -198,7 +198,7 @@ DIR_ITER* devoptab_diropen(struct _reent *r, DIR_ITER *dirState, const char *_pa auto dir = static_cast(dirState->dirStruct); std::memset(dir, 0, sizeof(*dir)); - char path[FS_MAX_PATH]; + char path[PATH_MAX]; if (!common::fix_path(_path, path)) { set_errno(r, ENOENT); return NULL; @@ -282,7 +282,7 @@ int devoptab_dirclose(struct _reent *r, DIR_ITER *dirState) { int devoptab_lstat(struct _reent *r, const char *_path, struct stat *st) { auto device = (Device*)r->deviceData; - char path[FS_MAX_PATH]; + char path[PATH_MAX]; if (!common::fix_path(_path, path)) { return set_errno(r, ENOENT); } diff --git a/sphaira/source/utils/devoptab_nsp.cpp b/sphaira/source/utils/devoptab_nsp.cpp index 0942d55..a11fb01 100644 --- a/sphaira/source/utils/devoptab_nsp.cpp +++ b/sphaira/source/utils/devoptab_nsp.cpp @@ -44,7 +44,7 @@ int devoptab_open(struct _reent *r, void *fileStruct, const char *_path, int fla auto file = static_cast(fileStruct); std::memset(file, 0, sizeof(*file)); - char path[FS_MAX_PATH]; + char path[PATH_MAX]; if (!common::fix_path(_path, path)) { return set_errno(r, ENOENT); } @@ -112,7 +112,7 @@ DIR_ITER* devoptab_diropen(struct _reent *r, DIR_ITER *dirState, const char *_pa auto dir = static_cast(dirState->dirStruct); std::memset(dir, 0, sizeof(*dir)); - char path[FS_MAX_PATH]; + char path[PATH_MAX]; if (!common::fix_path(_path, path)) { set_errno(r, ENOENT); return NULL; @@ -165,7 +165,7 @@ int devoptab_dirclose(struct _reent *r, DIR_ITER *dirState) { int devoptab_lstat(struct _reent *r, const char *_path, struct stat *st) { auto device = (Device*)r->deviceData; - char path[FS_MAX_PATH]; + char path[PATH_MAX]; if (!common::fix_path(_path, path)) { return set_errno(r, ENOENT); } diff --git a/sphaira/source/utils/devoptab_save.cpp b/sphaira/source/utils/devoptab_save.cpp index 82a9943..3781bb3 100644 --- a/sphaira/source/utils/devoptab_save.cpp +++ b/sphaira/source/utils/devoptab_save.cpp @@ -51,7 +51,7 @@ int devoptab_open(struct _reent *r, void *fileStruct, const char *_path, int fla auto file = static_cast(fileStruct); std::memset(file, 0, sizeof(*file)); - char path[FS_MAX_PATH]; + char path[PATH_MAX]; if (!common::fix_path(_path, path)) { return set_errno(r, ENOENT); } @@ -117,7 +117,7 @@ DIR_ITER* devoptab_diropen(struct _reent *r, DIR_ITER *dirState, const char *_pa auto dir = static_cast(dirState->dirStruct); std::memset(dir, 0, sizeof(*dir)); - char path[FS_MAX_PATH]; + char path[PATH_MAX]; if (!common::fix_path(_path, path)) { set_errno(r, ENOENT); return NULL; @@ -204,7 +204,7 @@ int devoptab_dirclose(struct _reent *r, DIR_ITER *dirState) { int devoptab_lstat(struct _reent *r, const char *_path, struct stat *st) { auto device = (Device*)r->deviceData; - char path[FS_MAX_PATH]; + char path[PATH_MAX]; if (!common::fix_path(_path, path)) { return set_errno(r, ENOENT); } diff --git a/sphaira/source/utils/devoptab_smb2.cpp b/sphaira/source/utils/devoptab_smb2.cpp index ca19023..c05e113 100644 --- a/sphaira/source/utils/devoptab_smb2.cpp +++ b/sphaira/source/utils/devoptab_smb2.cpp @@ -16,11 +16,16 @@ namespace sphaira::devoptab { namespace { +constexpr int DEFAULT_SMB2_TIMEOUT = 3000; // 3 seconds. + struct Smb2MountConfig { std::string name{}; std::string url{}; std::string user{}; std::string pass{}; + std::string domain{}; + std::string workstation{}; + int timeout{DEFAULT_SMB2_TIMEOUT}; bool read_only{}; }; using Smb2MountConfigs = std::vector; @@ -64,6 +69,16 @@ bool mount_smb2(Device& device) { if (!device.config.pass.empty()) { smb2_set_password(device.smb2, device.config.pass.c_str()); } + + if (!device.config.domain.empty()) { + smb2_set_domain(device.smb2, device.config.domain.c_str()); + } + + if (!device.config.workstation.empty()) { + smb2_set_workstation(device.smb2, device.config.workstation.c_str()); + } + + smb2_set_timeout(device.smb2, device.config.timeout); } if (!device.url) { @@ -74,10 +89,6 @@ bool mount_smb2(Device& device) { } } - log_write("[SMB2] Connecting to %s/%s as %s\n", - device.url->server, - device.url->share, - device.url->user ? device.url->user : "guest"); const auto ret = smb2_connect_share(device.smb2, device.url->server, device.url->share, device.url->user); if (ret) { log_write("[SMB2] smb2_connect_share() failed: %s errno: %s\n", smb2_get_error(device.smb2), std::strerror(-ret)); @@ -127,7 +138,7 @@ int devoptab_open(struct _reent *r, void *fileStruct, const char *_path, int fla return set_errno(r, EROFS); } - char path[FS_MAX_PATH]{}; + char path[PATH_MAX]{}; if (!fix_path(_path, path)) { return set_errno(r, ENOENT); } @@ -217,7 +228,7 @@ int devoptab_unlink(struct _reent *r, const char *_path) { auto device = static_cast(r->deviceData); SCOPED_MUTEX(&device->mutex); - char path[FS_MAX_PATH]{}; + char path[PATH_MAX]{}; if (!fix_path(_path, path)) { return set_errno(r, ENOENT); } @@ -239,12 +250,12 @@ int devoptab_rename(struct _reent *r, const char *_oldName, const char *_newName auto device = static_cast(r->deviceData); SCOPED_MUTEX(&device->mutex); - char oldName[FS_MAX_PATH]{}; + char oldName[PATH_MAX]{}; if (!fix_path(_oldName, oldName)) { return set_errno(r, ENOENT); } - char newName[FS_MAX_PATH]{}; + char newName[PATH_MAX]{}; if (!fix_path(_newName, newName)) { return set_errno(r, ENOENT); } @@ -266,7 +277,7 @@ int devoptab_mkdir(struct _reent *r, const char *_path, int mode) { auto device = static_cast(r->deviceData); SCOPED_MUTEX(&device->mutex); - char path[FS_MAX_PATH]{}; + char path[PATH_MAX]{}; if (!fix_path(_path, path)) { return set_errno(r, ENOENT); } @@ -288,7 +299,7 @@ int devoptab_rmdir(struct _reent *r, const char *_path) { auto device = static_cast(r->deviceData); SCOPED_MUTEX(&device->mutex); - char path[FS_MAX_PATH]{}; + char path[PATH_MAX]{}; if (!fix_path(_path, path)) { return set_errno(r, ENOENT); } @@ -312,7 +323,7 @@ DIR_ITER* devoptab_diropen(struct _reent *r, DIR_ITER *dirState, const char *_pa std::memset(dir, 0, sizeof(*dir)); SCOPED_MUTEX(&device->mutex); - char path[FS_MAX_PATH]{}; + char path[PATH_MAX]{}; if (!fix_path(_path, path)) { set_errno(r, ENOENT); return nullptr; @@ -376,7 +387,7 @@ int devoptab_lstat(struct _reent *r, const char *_path, struct stat *st) { std::memset(st, 0, sizeof(*st)); SCOPED_MUTEX(&device->mutex); - char path[FS_MAX_PATH]{}; + char path[PATH_MAX]{}; if (!fix_path(_path, path)) { return set_errno(r, ENOENT); } @@ -413,7 +424,7 @@ int devoptab_statvfs(struct _reent *r, const char *_path, struct statvfs *buf) { auto device = static_cast(r->deviceData); SCOPED_MUTEX(&device->mutex); - char path[FS_MAX_PATH]{}; + char path[PATH_MAX]{}; if (!fix_path(_path, path)) { return set_errno(r, ENOENT); } @@ -532,6 +543,12 @@ Result MountSmb2All() { e->back().user = Value; } else if (!std::strcmp(Key, "pass")) { e->back().pass = Value; + } else if (!std::strcmp(Key, "domain")) { + e->back().domain = Value; + } else if (!std::strcmp(Key, "workstation")) { + e->back().workstation = Value; + } else if (!std::strcmp(Key, "timeout")) { + e->back().timeout = ini_parse_getl(Value, DEFAULT_SMB2_TIMEOUT); } else if (!std::strcmp(Key, "read_only")) { e->back().read_only = ini_parse_getbool(Value, false); } else { @@ -576,8 +593,8 @@ Result MountSmb2All() { entry->devoptab.name = entry->name; entry->devoptab.deviceData = &entry->device; entry->device.config = config; - std::snprintf(entry->name, sizeof(entry->name), "%s", config.name.c_str()); - std::snprintf(entry->mount, sizeof(entry->mount), "%s:/", config.name.c_str()); + std::snprintf(entry->name, sizeof(entry->name), "[SMB] %s", config.name.c_str()); + std::snprintf(entry->mount, sizeof(entry->mount), "[SMB] %s:/", config.name.c_str()); common::update_devoptab_for_read_only(&entry->devoptab, config.read_only); R_UNLESS(AddDevice(&entry->devoptab) >= 0, 0x1); diff --git a/sphaira/source/utils/devoptab_xci.cpp b/sphaira/source/utils/devoptab_xci.cpp index 2c9c2cc..73f0a97 100644 --- a/sphaira/source/utils/devoptab_xci.cpp +++ b/sphaira/source/utils/devoptab_xci.cpp @@ -44,7 +44,7 @@ int devoptab_open(struct _reent *r, void *fileStruct, const char *_path, int fla auto file = static_cast(fileStruct); std::memset(file, 0, sizeof(*file)); - char path[FS_MAX_PATH]; + char path[PATH_MAX]; if (!common::fix_path(_path, path)) { return set_errno(r, ENOENT); } @@ -114,7 +114,7 @@ DIR_ITER* devoptab_diropen(struct _reent *r, DIR_ITER *dirState, const char *_pa auto dir = static_cast(dirState->dirStruct); std::memset(dir, 0, sizeof(*dir)); - char path[FS_MAX_PATH]; + char path[PATH_MAX]; if (!common::fix_path(_path, path)) { set_errno(r, ENOENT); return NULL; @@ -184,7 +184,7 @@ int devoptab_dirclose(struct _reent *r, DIR_ITER *dirState) { int devoptab_lstat(struct _reent *r, const char *_path, struct stat *st) { auto device = (Device*)r->deviceData; - char path[FS_MAX_PATH]; + char path[PATH_MAX]; if (!common::fix_path(_path, path)) { return set_errno(r, ENOENT); } diff --git a/sphaira/source/utils/devoptab_zip.cpp b/sphaira/source/utils/devoptab_zip.cpp index e20a129..adbb43e 100644 --- a/sphaira/source/utils/devoptab_zip.cpp +++ b/sphaira/source/utils/devoptab_zip.cpp @@ -204,7 +204,7 @@ int devoptab_open(struct _reent *r, void *fileStruct, const char *_path, int fla auto file = static_cast(fileStruct); std::memset(file, 0, sizeof(*file)); - char path[FS_MAX_PATH]{}; + char path[PATH_MAX]{}; if (!common::fix_path(_path, path)) { return set_errno(r, ENOENT); } @@ -382,7 +382,7 @@ DIR_ITER* devoptab_diropen(struct _reent *r, DIR_ITER *dirState, const char *_pa auto dir = static_cast(dirState->dirStruct); std::memset(dir, 0, sizeof(*dir)); - char path[FS_MAX_PATH]; + char path[PATH_MAX]; if (!common::fix_path(_path, path)) { set_errno(r, ENOENT); return NULL; @@ -451,7 +451,7 @@ int devoptab_lstat(struct _reent *r, const char *_path, struct stat *st) { return set_errno(r, ENOENT); } - char path[FS_MAX_PATH]; + char path[PATH_MAX]; if (!common::fix_path(_path, path)) { return set_errno(r, ENOENT); } diff --git a/sphaira/source/web.cpp b/sphaira/source/web.cpp index 29fa380..4cd161b 100644 --- a/sphaira/source/web.cpp +++ b/sphaira/source/web.cpp @@ -11,8 +11,6 @@ auto WebShow(const std::string& url) -> Result { WebCommonReply reply{}; WebExitReason reason{}; AccountUid account_uid{}; - char last_url[FS_MAX_PATH]{}; - size_t last_url_len{}; // WebBackgroundKind_Unknown1 = shows background // WebBackgroundKind_Unknown2 = shows background faded @@ -54,8 +52,6 @@ auto WebShow(const std::string& url) -> Result { if (R_FAILED(webConfigShow(&config, &reply))) { log_write("failed: webConfigShow\n"); } if (R_FAILED(webReplyGetExitReason(&reply, &reason))) { log_write("failed: webReplyGetExitReason\n"); } - if (R_FAILED(webReplyGetLastUrl(&reply, last_url, sizeof(last_url), &last_url_len))) { log_write("failed: webReplyGetLastUrl\n"); } - log_write("last url: %s\n", last_url); R_SUCCEED(); }