mirror of
https://github.com/wiiu-env/ftpiiu_plugin.git
synced 2024-12-22 11:01:48 +01:00
wiiu: working as a plugin
This commit is contained in:
parent
af2b1be4c8
commit
40ff376710
1
.gitignore
vendored
1
.gitignore
vendored
@ -27,3 +27,4 @@ switch/romfs/shaders/*.dksh
|
||||
build/
|
||||
*.rpx
|
||||
*.wuhb
|
||||
*.wps
|
||||
|
6
Dockerfile.wiiu
Normal file
6
Dockerfile.wiiu
Normal file
@ -0,0 +1,6 @@
|
||||
FROM ghcr.io/wiiu-env/devkitppc:20231112
|
||||
|
||||
COPY --from=ghcr.io/wiiu-env/wiiupluginsystem:20230719 /artifacts $DEVKITPRO
|
||||
COPY --from=ghcr.io/wiiu-env/libmocha:20230621 /artifacts $DEVKITPRO
|
||||
|
||||
WORKDIR project
|
@ -8,16 +8,10 @@ endif
|
||||
|
||||
TOPDIR ?= $(CURDIR)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# APP_NAME sets the long name of the application
|
||||
# APP_SHORTNAME sets the short name of the application
|
||||
# APP_AUTHOR sets the author of the application
|
||||
#-------------------------------------------------------------------------------
|
||||
#APP_NAME := Application Name
|
||||
#APP_SHORTNAME := App Name
|
||||
#APP_AUTHOR := Built with devkitPPC & wut
|
||||
include $(DEVKITPRO)/wups/share/wups_rules
|
||||
|
||||
include $(DEVKITPRO)/wut/share/wut_rules
|
||||
WUT_ROOT := $(DEVKITPRO)/wut
|
||||
WUPS_ROOT := $(DEVKITPRO)/wups
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
@ -25,42 +19,44 @@ include $(DEVKITPRO)/wut/share/wut_rules
|
||||
# SOURCES is a list of directories containing source code
|
||||
# DATA is a list of directories containing data files
|
||||
# INCLUDES is a list of directories containing header files
|
||||
# CONTENT is the path to the bundled folder that will be mounted as /vol/content/
|
||||
# ICON is the game icon, leave blank to use default rule
|
||||
# TV_SPLASH is the image displayed during bootup on the TV, leave blank to use default rule
|
||||
# DRC_SPLASH is the image displayed during bootup on the DRC, leave blank to use default rule
|
||||
#-------------------------------------------------------------------------------
|
||||
TARGET := $(notdir $(CURDIR))
|
||||
TARGET := ftpd
|
||||
BUILD := build
|
||||
SOURCES := source source/wiiu
|
||||
DATA := data
|
||||
INCLUDES := include
|
||||
CONTENT :=
|
||||
ICON :=
|
||||
TV_SPLASH :=
|
||||
DRC_SPLASH :=
|
||||
INCLUDES := source include
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#-------------------------------------------------------------------------------
|
||||
CFLAGS := -g -Wall -O0 -ffunction-sections \
|
||||
CFLAGS := -Wall -O2 -ffunction-sections \
|
||||
$(MACHDEP)
|
||||
|
||||
CFLAGS += $(INCLUDE) -D__WIIU__ -D__WUT__ -DSTATUS_STRING="\"ftpd v$(VERSION)\"" \
|
||||
|
||||
CFLAGS += $(INCLUDE) -D__WIIU__ -D__WUT__ -D__WUPS__ -DSTATUS_STRING="\"ftpd v$(VERSION)\"" \
|
||||
-DNO_IPV6 -DCLASSIC -DNO_CONSOLE -DFTPDCONFIG="\"/config/ftpd/ftpd.cfg\""
|
||||
|
||||
CXXFLAGS := $(CFLAGS) -std=c++20
|
||||
CXXFLAGS := $(CFLAGS) -std=gnu++20
|
||||
|
||||
ASFLAGS := -g $(ARCH)
|
||||
LDFLAGS = -g $(ARCH) $(RPXSPECS) -Wl,-Map,$(notdir $*.map)
|
||||
LDFLAGS = -g $(ARCH) $(RPXSPECS) -Wl,-Map,$(notdir $*.map) $(WUPSSPECS)
|
||||
|
||||
LIBS := -lwutd -lmocha
|
||||
ifeq ($(DEBUG),1)
|
||||
CXXFLAGS += -DDEBUG -g
|
||||
CFLAGS += -DDEBUG -g
|
||||
endif
|
||||
|
||||
ifeq ($(DEBUG),VERBOSE)
|
||||
CXXFLAGS += -DDEBUG -DVERBOSE_DEBUG -g
|
||||
CFLAGS += -DDEBUG -DVERBOSE_DEBUG -g
|
||||
endif
|
||||
|
||||
LIBS := -lwups -lwutd -lmocha
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level
|
||||
# containing include and lib
|
||||
#-------------------------------------------------------------------------------
|
||||
LIBDIRS := $(PORTLIBS) $(WUT_ROOT) $(WUT_ROOT)/usr
|
||||
LIBDIRS := $(PORTLIBS) $(WUPS_ROOT) $(WUT_ROOT) $(WUT_ROOT)/usr
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# no real need to edit anything past this point unless you need to add additional
|
||||
@ -107,34 +103,6 @@ export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||
|
||||
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||
|
||||
ifneq (,$(strip $(CONTENT)))
|
||||
export APP_CONTENT := $(TOPDIR)/$(CONTENT)
|
||||
endif
|
||||
|
||||
ifneq (,$(strip $(ICON)))
|
||||
export APP_ICON := $(TOPDIR)/$(ICON)
|
||||
else ifneq (,$(wildcard $(TOPDIR)/$(TARGET).png))
|
||||
export APP_ICON := $(TOPDIR)/$(TARGET).png
|
||||
else ifneq (,$(wildcard $(TOPDIR)/icon.png))
|
||||
export APP_ICON := $(TOPDIR)/icon.png
|
||||
endif
|
||||
|
||||
ifneq (,$(strip $(TV_SPLASH)))
|
||||
export APP_TV_SPLASH := $(TOPDIR)/$(TV_SPLASH)
|
||||
else ifneq (,$(wildcard $(TOPDIR)/tv-splash.png))
|
||||
export APP_TV_SPLASH := $(TOPDIR)/tv-splash.png
|
||||
else ifneq (,$(wildcard $(TOPDIR)/splash.png))
|
||||
export APP_TV_SPLASH := $(TOPDIR)/splash.png
|
||||
endif
|
||||
|
||||
ifneq (,$(strip $(DRC_SPLASH)))
|
||||
export APP_DRC_SPLASH := $(TOPDIR)/$(DRC_SPLASH)
|
||||
else ifneq (,$(wildcard $(TOPDIR)/drc-splash.png))
|
||||
export APP_DRC_SPLASH := $(TOPDIR)/drc-splash.png
|
||||
else ifneq (,$(wildcard $(TOPDIR)/splash.png))
|
||||
export APP_DRC_SPLASH := $(TOPDIR)/splash.png
|
||||
endif
|
||||
|
||||
.PHONY: $(BUILD) clean all
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
@ -147,7 +115,7 @@ $(BUILD):
|
||||
#-------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@rm -fr $(BUILD) $(TARGET).wuhb $(TARGET).rpx $(TARGET).elf
|
||||
@rm -fr $(BUILD) $(TARGET).wps $(TARGET).elf
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
else
|
||||
@ -158,10 +126,9 @@ DEPENDS := $(OFILES:.o=.d)
|
||||
#-------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#-------------------------------------------------------------------------------
|
||||
all : $(OUTPUT).wuhb
|
||||
all : $(OUTPUT).wps
|
||||
|
||||
$(OUTPUT).wuhb : $(OUTPUT).rpx
|
||||
$(OUTPUT).rpx : $(OUTPUT).elf
|
||||
$(OUTPUT).wps : $(OUTPUT).elf
|
||||
$(OUTPUT).elf : $(OFILES)
|
||||
|
||||
$(OFILES_SRC) : $(HFILES_BIN)
|
||||
|
@ -20,7 +20,6 @@ public:
|
||||
|
||||
static int closedir (DIR *dirp);
|
||||
|
||||
|
||||
static DIR *opendir (const char *dirname);
|
||||
|
||||
static struct dirent *readdir (DIR *dirp);
|
||||
@ -29,6 +28,16 @@ public:
|
||||
|
||||
static int lstat (const char *path, struct stat *buf);
|
||||
|
||||
static int mkdir (const char *path, mode_t mode);
|
||||
|
||||
static int rmdir (const char *path);
|
||||
|
||||
static int rename (const char *path, const char *path2);
|
||||
|
||||
static int unlink (const char *path);
|
||||
|
||||
static void addVirtualPath (const std::string &virtualPath,
|
||||
const std::vector<std::string> &subDirectories);
|
||||
|
||||
static void clear ();
|
||||
};
|
@ -60,13 +60,7 @@ private:
|
||||
/// \brief Command buffer size
|
||||
constexpr static auto COMMAND_BUFFERSIZE = 4096;
|
||||
|
||||
#ifdef __WIIU__
|
||||
/// \brief Response buffer size
|
||||
constexpr static auto RESPONSE_BUFFERSIZE = 128 * 1024;
|
||||
|
||||
/// \brief Transfer buffersize
|
||||
constexpr static auto XFER_BUFFERSIZE = 128 * 1024;
|
||||
#elif defined(NDS)
|
||||
#ifdef NDS
|
||||
/// \brief Response buffer size
|
||||
constexpr static auto RESPONSE_BUFFERSIZE = 4096;
|
||||
|
||||
@ -74,10 +68,10 @@ private:
|
||||
constexpr static auto XFER_BUFFERSIZE = 8192;
|
||||
#else
|
||||
/// \brief Response buffer size
|
||||
constexpr static auto RESPONSE_BUFFERSIZE = 32768;
|
||||
constexpr static auto RESPONSE_BUFFERSIZE = 16 * 1024;
|
||||
|
||||
/// \brief Transfer buffersize
|
||||
constexpr static auto XFER_BUFFERSIZE = 65536;
|
||||
constexpr static auto XFER_BUFFERSIZE = 32 * 1024;
|
||||
#endif
|
||||
|
||||
/// \brief File buffersize
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <sys/dirent.h>
|
||||
#include <sys/unistd.h>
|
||||
#include <vector>
|
||||
|
||||
class VirtualDirectory
|
||||
@ -17,9 +18,9 @@ public:
|
||||
mCurIterator = mDirectories.begin ();
|
||||
}
|
||||
|
||||
[[nodiscard]] DIR *getAsDir () const
|
||||
[[nodiscard]] const DIR *getAsDir () const
|
||||
{
|
||||
return (DIR *)this;
|
||||
return &mDirPtr;
|
||||
}
|
||||
|
||||
struct dirent *readdir ()
|
||||
@ -31,10 +32,12 @@ public:
|
||||
mDir = {};
|
||||
snprintf (mDir.d_name, sizeof (mDir.d_name), "%s", mCurIterator->c_str ());
|
||||
mCurIterator++;
|
||||
mDirPtr.position++;
|
||||
return &mDir;
|
||||
}
|
||||
|
||||
private:
|
||||
DIR mDirPtr = {};
|
||||
std::vector<std::string> mDirectories;
|
||||
struct dirent mDir = {};
|
||||
std::vector<std::string>::iterator mCurIterator{};
|
||||
@ -70,7 +73,7 @@ bool remove_locked_first_if (std::mutex &mutex, Container &container, Predicate
|
||||
return remove_first_if (container, pred);
|
||||
}
|
||||
|
||||
static DIR *getVirtualDir (const std::vector<std::string> &subDirectories)
|
||||
static const DIR *getVirtualDir (const std::vector<std::string> &subDirectories)
|
||||
{
|
||||
auto virtDir = std::make_unique<VirtualDirectory> (subDirectories);
|
||||
auto *result = virtDir->getAsDir ();
|
||||
@ -124,12 +127,16 @@ int IOAbstraction::closedir (DIR *dirp)
|
||||
DIR *IOAbstraction::opendir (const char *dirname)
|
||||
{
|
||||
auto convertedPath = convertPath (dirname);
|
||||
if (sVirtualDirs.count (convertedPath) > 0)
|
||||
auto * res = ::opendir (convertedPath.c_str ());
|
||||
if(res == nullptr)
|
||||
{
|
||||
return getVirtualDir (sVirtualDirs[convertedPath]);
|
||||
}
|
||||
if (sVirtualDirs.count (convertedPath) > 0)
|
||||
{
|
||||
return (DIR*) getVirtualDir (sVirtualDirs[convertedPath]);
|
||||
}
|
||||
|
||||
return ::opendir (convertedPath.c_str ());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
FILE *IOAbstraction::fopen (const char *_name, const char *_type)
|
||||
@ -195,3 +202,30 @@ void IOAbstraction::addVirtualPath (const std::string &virtualPath,
|
||||
{
|
||||
sVirtualDirs.insert (std::make_pair (virtualPath, subDirectories));
|
||||
}
|
||||
|
||||
void IOAbstraction::clear ()
|
||||
{
|
||||
std::lock_guard lock (sOpenVirtualDirectoriesMutex);
|
||||
sOpenVirtualDirectories.clear ();
|
||||
sVirtualDirs.clear ();
|
||||
}
|
||||
|
||||
int IOAbstraction::mkdir (const char *path, mode_t mode)
|
||||
{
|
||||
return ::mkdir (convertPath (path).c_str (), mode);
|
||||
}
|
||||
|
||||
int IOAbstraction::rmdir (const char *path)
|
||||
{
|
||||
return ::rmdir (convertPath (path).c_str ());
|
||||
}
|
||||
|
||||
int IOAbstraction::unlink (const char *path)
|
||||
{
|
||||
return ::unlink (convertPath (path).c_str ());
|
||||
}
|
||||
|
||||
int IOAbstraction::rename (const char *path, const char *path2)
|
||||
{
|
||||
return ::rename (convertPath (path).c_str (), convertPath (path2).c_str ());
|
||||
}
|
||||
|
@ -583,10 +583,20 @@ bool FtpSession::poll (std::vector<UniqueFtpSession> const &sessions_)
|
||||
}
|
||||
else if (i.revents & (POLLIN | POLLOUT))
|
||||
{
|
||||
for (unsigned i = 0; i < 10; ++i)
|
||||
auto start_time = std::chrono::high_resolution_clock::now ();
|
||||
while (true)
|
||||
{
|
||||
if (!((*session).*(session->m_transfer)) ())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (std::chrono::duration_cast<std::chrono::microseconds> (
|
||||
std::chrono::high_resolution_clock::now () - start_time) >
|
||||
5000ms)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -1677,7 +1687,7 @@ bool FtpSession::listTransfer ()
|
||||
{
|
||||
// build the path
|
||||
auto const fullPath = buildPath (m_lwd, dent->d_name);
|
||||
struct stat st;
|
||||
struct stat st = {};
|
||||
|
||||
#ifdef __3DS__
|
||||
// the sdmc directory entry already has the type and size, so no need to do a slow stat
|
||||
@ -1997,7 +2007,7 @@ void FtpSession::DELE (char const *args_)
|
||||
}
|
||||
|
||||
// unlink the path
|
||||
if (::unlink (path.c_str ()) != 0)
|
||||
if (IOAbstraction::unlink (path.c_str ()) != 0)
|
||||
{
|
||||
sendResponse ("550 %s\r\n", std::strerror (errno));
|
||||
return;
|
||||
@ -2081,7 +2091,7 @@ void FtpSession::MKD (char const *args_)
|
||||
}
|
||||
|
||||
// create the directory
|
||||
if (::mkdir (path.c_str (), 0755) != 0)
|
||||
if (IOAbstraction::mkdir (path.c_str (), 0755) != 0)
|
||||
{
|
||||
sendResponse ("550 %s\r\n", std::strerror (errno));
|
||||
return;
|
||||
@ -2498,7 +2508,7 @@ void FtpSession::RMD (char const *args_)
|
||||
}
|
||||
|
||||
// remove the directory
|
||||
if (::rmdir (path.c_str ()) != 0)
|
||||
if (IOAbstraction::rmdir (path.c_str ()) != 0)
|
||||
{
|
||||
sendResponse ("550 %d %s\r\n", __LINE__, std::strerror (errno));
|
||||
return;
|
||||
@ -2566,7 +2576,7 @@ void FtpSession::RNTO (char const *args_)
|
||||
}
|
||||
|
||||
// rename the file
|
||||
if (::rename (m_rename.c_str (), path.c_str ()) != 0)
|
||||
if (IOAbstraction::rename (m_rename.c_str (), path.c_str ()) != 0)
|
||||
{
|
||||
m_rename.clear ();
|
||||
sendResponse ("550 %s\r\n", std::strerror (errno));
|
||||
|
@ -20,7 +20,8 @@
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
#include "../IOAbstraction.h"
|
||||
#include "IOAbstraction.h"
|
||||
#include "ftpServer.h"
|
||||
#include "log.h"
|
||||
|
||||
#include <mocha/mocha.h>
|
||||
@ -28,12 +29,29 @@
|
||||
#include <thread>
|
||||
|
||||
#include <coreinit/thread.h>
|
||||
#include <sys/unistd.h>
|
||||
#include <whb/proc.h>
|
||||
#include <wups.h>
|
||||
#include <wups/config/WUPSConfigCategory.h>
|
||||
#include <wups/config/WUPSConfigItem.h>
|
||||
#include <wups/config/WUPSConfigItemBoolean.h>
|
||||
#include <wups/config/WUPSConfigItemStub.h>
|
||||
|
||||
#ifndef CLASSIC
|
||||
#error "Wii U must be built in classic mode"
|
||||
#endif
|
||||
#define VERSION_FULL "0.1"
|
||||
|
||||
WUPS_PLUGIN_NAME ("ftpd");
|
||||
WUPS_PLUGIN_DESCRIPTION ("FTP Server");
|
||||
WUPS_PLUGIN_VERSION (VERSION_FULL);
|
||||
WUPS_PLUGIN_AUTHOR ("mtheall, Maschell");
|
||||
WUPS_PLUGIN_LICENSE ("GPL");
|
||||
|
||||
WUPS_USE_WUT_DEVOPTAB ();
|
||||
WUPS_USE_STORAGE ("ftpd"); // Unqiue id for the storage api
|
||||
|
||||
#define FTPIIU_ENABLED_STRING "enabled"
|
||||
#define SYSTEM_FILES_ALLOWED_STRING "systemFilesAllowed"
|
||||
|
||||
bool platform::networkVisible ()
|
||||
{
|
||||
@ -68,71 +86,262 @@ MochaUtilsStatus MountWrapper (const char *mount, const char *dev, const char *m
|
||||
return res;
|
||||
}
|
||||
|
||||
bool platform::init ()
|
||||
UniqueFtpServer server = nullptr;
|
||||
bool sSystemFilesAllowed = false;
|
||||
bool sMochaPathsWereMounted = false;
|
||||
bool sFTPServerEnabled = true;
|
||||
|
||||
void start_server ()
|
||||
{
|
||||
nn::ac::Initialize ();
|
||||
nn::ac::ConnectAsync ();
|
||||
WHBProcInit ();
|
||||
if (server != nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MochaUtilsStatus res;
|
||||
if ((res = Mocha_InitLibrary ()) == MOCHA_RESULT_SUCCESS)
|
||||
{
|
||||
std::vector<std::string> virtualDirsInRoot;
|
||||
if (MountWrapper ("slccmpt01", "/dev/slccmpt01", "/vol/storage_slccmpt01") ==
|
||||
MOCHA_RESULT_SUCCESS)
|
||||
if (sSystemFilesAllowed)
|
||||
{
|
||||
virtualDirsInRoot.push_back ("slccmpt01");
|
||||
if (MountWrapper ("slccmpt01", "/dev/slccmpt01", "/vol/storage_slccmpt01") ==
|
||||
MOCHA_RESULT_SUCCESS)
|
||||
{
|
||||
virtualDirsInRoot.emplace_back ("slccmpt01");
|
||||
IOAbstraction::addVirtualPath ("slccmpt01:/", {});
|
||||
}
|
||||
if (MountWrapper ("storage_odd_tickets", nullptr, "/vol/storage_odd01") ==
|
||||
MOCHA_RESULT_SUCCESS)
|
||||
{
|
||||
virtualDirsInRoot.emplace_back ("storage_odd_tickets");
|
||||
IOAbstraction::addVirtualPath ("storage_odd_tickets:/", {});
|
||||
}
|
||||
if (MountWrapper ("storage_odd_updates", nullptr, "/vol/storage_odd02") ==
|
||||
MOCHA_RESULT_SUCCESS)
|
||||
{
|
||||
virtualDirsInRoot.emplace_back ("storage_odd_updates");
|
||||
IOAbstraction::addVirtualPath ("storage_odd_updates:/", {});
|
||||
}
|
||||
if (MountWrapper ("storage_odd_content", nullptr, "/vol/storage_odd03") ==
|
||||
MOCHA_RESULT_SUCCESS)
|
||||
{
|
||||
virtualDirsInRoot.emplace_back ("storage_odd_content");
|
||||
IOAbstraction::addVirtualPath ("storage_odd_content:/", {});
|
||||
}
|
||||
if (MountWrapper ("storage_odd_content2", nullptr, "/vol/storage_odd04") ==
|
||||
MOCHA_RESULT_SUCCESS)
|
||||
{
|
||||
virtualDirsInRoot.emplace_back ("storage_odd_content2");
|
||||
IOAbstraction::addVirtualPath ("storage_odd_content2:/", {});
|
||||
}
|
||||
if (MountWrapper ("storage_slc", "/dev/slc01", "/vol/storage_slc01") ==
|
||||
MOCHA_RESULT_SUCCESS)
|
||||
{
|
||||
virtualDirsInRoot.emplace_back ("storage_slc");
|
||||
IOAbstraction::addVirtualPath ("storage_slc:/", {});
|
||||
}
|
||||
if (Mocha_MountFS ("storage_mlc", nullptr, "/vol/storage_mlc01") ==
|
||||
MOCHA_RESULT_SUCCESS)
|
||||
{
|
||||
virtualDirsInRoot.emplace_back ("storage_mlc");
|
||||
IOAbstraction::addVirtualPath ("storage_mlc:/", {});
|
||||
}
|
||||
if (Mocha_MountFS ("storage_usb", nullptr, "/vol/storage_usb01") ==
|
||||
MOCHA_RESULT_SUCCESS)
|
||||
{
|
||||
virtualDirsInRoot.emplace_back ("storage_usb");
|
||||
IOAbstraction::addVirtualPath ("storage_usb:/", {});
|
||||
}
|
||||
}
|
||||
if (MountWrapper ("storage_odd_tickets", nullptr, "/vol/storage_odd01") ==
|
||||
MOCHA_RESULT_SUCCESS)
|
||||
{
|
||||
virtualDirsInRoot.push_back ("storage_odd_tickets");
|
||||
}
|
||||
if (MountWrapper ("storage_odd_updates", nullptr, "/vol/storage_odd02") ==
|
||||
MOCHA_RESULT_SUCCESS)
|
||||
{
|
||||
virtualDirsInRoot.push_back ("storage_odd_updates");
|
||||
}
|
||||
if (MountWrapper ("storage_odd_content", nullptr, "/vol/storage_odd03") ==
|
||||
MOCHA_RESULT_SUCCESS)
|
||||
{
|
||||
virtualDirsInRoot.push_back ("storage_odd_content");
|
||||
}
|
||||
if (MountWrapper ("storage_odd_content2", nullptr, "/vol/storage_odd04") ==
|
||||
MOCHA_RESULT_SUCCESS)
|
||||
{
|
||||
virtualDirsInRoot.push_back ("storage_odd_content2");
|
||||
}
|
||||
if (MountWrapper ("storage_slc", "/dev/slc01", "/vol/storage_slc01") ==
|
||||
MOCHA_RESULT_SUCCESS)
|
||||
{
|
||||
virtualDirsInRoot.push_back ("storage_slc");
|
||||
}
|
||||
if (Mocha_MountFS ("storage_mlc", nullptr, "/vol/storage_mlc01") == MOCHA_RESULT_SUCCESS)
|
||||
{
|
||||
virtualDirsInRoot.push_back ("storage_mlc");
|
||||
}
|
||||
if (Mocha_MountFS ("storage_usb", nullptr, "/vol/storage_usb01") == MOCHA_RESULT_SUCCESS)
|
||||
{
|
||||
virtualDirsInRoot.push_back ("storage_usb");
|
||||
}
|
||||
virtualDirsInRoot.push_back ("fs");
|
||||
virtualDirsInRoot.emplace_back ("fs");
|
||||
IOAbstraction::addVirtualPath (":/", virtualDirsInRoot);
|
||||
IOAbstraction::addVirtualPath ("fs:/", std::vector<std::string>{"vol"});
|
||||
IOAbstraction::addVirtualPath ("fs:/vol", std::vector<std::string>{"external01"});
|
||||
IOAbstraction::addVirtualPath ("storage_odd_tickets:/", {});
|
||||
IOAbstraction::addVirtualPath ("storage_odd_updates:/", {});
|
||||
IOAbstraction::addVirtualPath ("storage_odd_content:/", {});
|
||||
IOAbstraction::addVirtualPath ("storage_odd_content2:/", {});
|
||||
IOAbstraction::addVirtualPath ("storage_usb:/", {});
|
||||
IOAbstraction::addVirtualPath (
|
||||
"fs:/vol", std::vector<std::string>{"external01", "content", "save"});
|
||||
|
||||
IOAbstraction::addVirtualPath ("fs:/vol/content", {});
|
||||
sMochaPathsWereMounted = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
error ("Failed to init libmocha: %s [%d]", Mocha_GetStatusStr (res), res);
|
||||
OSReport ("Failed to init libmocha: %s [%d]\n", Mocha_GetStatusStr (res), res);
|
||||
}
|
||||
|
||||
::chdir ("fs:/vol/external01");
|
||||
server = FtpServer::create ();
|
||||
}
|
||||
|
||||
void stop_server ()
|
||||
{
|
||||
server.reset ();
|
||||
if (sMochaPathsWereMounted)
|
||||
{
|
||||
Mocha_UnmountFS ("slccmpt01");
|
||||
Mocha_UnmountFS ("storage_odd_tickets");
|
||||
Mocha_UnmountFS ("storage_odd_updates");
|
||||
Mocha_UnmountFS ("storage_odd_content");
|
||||
Mocha_UnmountFS ("storage_odd_content2");
|
||||
Mocha_UnmountFS ("storage_slc");
|
||||
Mocha_UnmountFS ("storage_mlc");
|
||||
Mocha_UnmountFS ("storage_usb");
|
||||
sMochaPathsWereMounted = false;
|
||||
}
|
||||
|
||||
IOAbstraction::clear ();
|
||||
}
|
||||
|
||||
void gFTPServerRunningChanged (ConfigItemBoolean *item, bool newValue)
|
||||
{
|
||||
sFTPServerEnabled = newValue;
|
||||
if (!sFTPServerEnabled)
|
||||
{
|
||||
stop_server ();
|
||||
}
|
||||
else
|
||||
{
|
||||
start_server ();
|
||||
}
|
||||
// If the value has changed, we store it in the storage.
|
||||
auto res = WUPSStorageAPI::Store (FTPIIU_ENABLED_STRING, sFTPServerEnabled);
|
||||
if (res != WUPS_STORAGE_ERROR_SUCCESS)
|
||||
{
|
||||
OSReport ("Failed to store gFTPServerEnabled: %s (%d)\n",
|
||||
WUPSStorageAPI::GetStatusStr (res).data (),
|
||||
res);
|
||||
}
|
||||
}
|
||||
|
||||
void gSystemFilesAllowedChanged (ConfigItemBoolean *item, bool newValue)
|
||||
{
|
||||
// DEBUG_FUNCTION_LINE("New value in gFTPServerEnabled: %d", newValue);
|
||||
if (server != nullptr)
|
||||
{ // If the server is already running we need to restart it.
|
||||
stop_server ();
|
||||
sSystemFilesAllowed = newValue;
|
||||
start_server ();
|
||||
}
|
||||
else
|
||||
{
|
||||
sSystemFilesAllowed = newValue;
|
||||
}
|
||||
// If the value has changed, we store it in the storage.
|
||||
auto res = WUPSStorageAPI::Store (SYSTEM_FILES_ALLOWED_STRING, sSystemFilesAllowed);
|
||||
if (res != WUPS_STORAGE_ERROR_SUCCESS)
|
||||
{
|
||||
OSReport ("Failed to store gSystemFilesAllowed: %s (%d)\n",
|
||||
WUPSStorageAPI::GetStatusStr (res).data (),
|
||||
res);
|
||||
}
|
||||
}
|
||||
|
||||
WUPSConfigAPICallbackStatus ConfigMenuOpenedCallback (WUPSConfigCategoryHandle rootHandle)
|
||||
{
|
||||
uint32_t hostIpAddress = 0;
|
||||
nn::ac::GetAssignedAddress (&hostIpAddress);
|
||||
try
|
||||
{
|
||||
WUPSConfigCategory root = WUPSConfigCategory (rootHandle);
|
||||
root.add (WUPSConfigItemBoolean::Create (FTPIIU_ENABLED_STRING,
|
||||
"Enable ftpd",
|
||||
true,
|
||||
sFTPServerEnabled,
|
||||
&gFTPServerRunningChanged));
|
||||
|
||||
root.add (WUPSConfigItemBoolean::Create (SYSTEM_FILES_ALLOWED_STRING,
|
||||
"Allow access to system files",
|
||||
false,
|
||||
sSystemFilesAllowed,
|
||||
&gSystemFilesAllowedChanged));
|
||||
|
||||
root.add (WUPSConfigItemStub::Create ("==="));
|
||||
|
||||
char ipSettings[50];
|
||||
if (hostIpAddress != 0)
|
||||
{
|
||||
snprintf (ipSettings,
|
||||
50,
|
||||
"IP of your console is %u.%u.%u.%u. Port %i",
|
||||
(hostIpAddress >> 24) & 0xFF,
|
||||
(hostIpAddress >> 16) & 0xFF,
|
||||
(hostIpAddress >> 8) & 0xFF,
|
||||
(hostIpAddress >> 0) & 0xFF,
|
||||
5000);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf (
|
||||
ipSettings, sizeof (ipSettings), "The console is not connected to a network.");
|
||||
}
|
||||
|
||||
root.add (WUPSConfigItemStub::Create (ipSettings));
|
||||
root.add (WUPSConfigItemStub::Create ("You can connect with empty credentials"));
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
OSReport ("Exception T_T : %s\n", e.what ());
|
||||
return WUPSCONFIG_API_CALLBACK_RESULT_ERROR;
|
||||
}
|
||||
|
||||
return WUPSCONFIG_API_CALLBACK_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
void ConfigMenuClosedCallback ()
|
||||
{
|
||||
OSReport ("ConfigMenuClosedCallback\n");
|
||||
WUPSStorageAPI::SaveStorage ();
|
||||
}
|
||||
|
||||
INITIALIZE_PLUGIN ()
|
||||
{
|
||||
WUPSConfigAPIOptionsV1 configOptions = {.name = "ftpd"};
|
||||
if (WUPSConfigAPI_Init (configOptions, ConfigMenuOpenedCallback, ConfigMenuClosedCallback) !=
|
||||
WUPSCONFIG_API_RESULT_SUCCESS)
|
||||
{
|
||||
OSFatal ("Failed to init config api");
|
||||
}
|
||||
|
||||
if (WUPSStorageAPI::GetOrStoreDefault (FTPIIU_ENABLED_STRING, sFTPServerEnabled, true) !=
|
||||
WUPS_STORAGE_ERROR_SUCCESS)
|
||||
{
|
||||
OSReport ("Failed\n");
|
||||
}
|
||||
if (WUPSStorageAPI::GetOrStoreDefault (
|
||||
SYSTEM_FILES_ALLOWED_STRING, sSystemFilesAllowed, false) != WUPS_STORAGE_ERROR_SUCCESS)
|
||||
{
|
||||
OSReport ("Failed\n");
|
||||
}
|
||||
if (WUPSStorageAPI::SaveStorage () != WUPS_STORAGE_ERROR_SUCCESS)
|
||||
{
|
||||
OSReport ("Failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
void wiiu_init ()
|
||||
{
|
||||
nn::ac::Initialize ();
|
||||
nn::ac::ConnectAsync ();
|
||||
if (sFTPServerEnabled)
|
||||
{
|
||||
start_server ();
|
||||
}
|
||||
}
|
||||
|
||||
ON_APPLICATION_START ()
|
||||
{
|
||||
nn::ac::Initialize ();
|
||||
nn::ac::ConnectAsync ();
|
||||
|
||||
wiiu_init ();
|
||||
}
|
||||
|
||||
ON_APPLICATION_ENDS ()
|
||||
{
|
||||
stop_server ();
|
||||
}
|
||||
|
||||
bool platform::init ()
|
||||
{
|
||||
WHBProcInit ();
|
||||
wiiu_init ();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -147,6 +356,7 @@ void platform::render ()
|
||||
|
||||
void platform::exit ()
|
||||
{
|
||||
IOAbstraction::clear ();
|
||||
WHBProcShutdown ();
|
||||
}
|
||||
|
||||
@ -162,11 +372,15 @@ public:
|
||||
explicit privateData_t (std::function<void ()> &&func_) : thread (std::move (func_))
|
||||
{
|
||||
auto nativeHandle = (OSThread *)thread.native_handle ();
|
||||
OSSetThreadName (nativeHandle, "ftpd_server");
|
||||
OSSetThreadName (nativeHandle, "ftpd");
|
||||
while (!OSSetThreadAffinity (nativeHandle, OS_THREAD_ATTRIB_AFFINITY_CPU2))
|
||||
{
|
||||
OSSleepTicks (OSMillisecondsToTicks (16));
|
||||
}
|
||||
while (!OSSetThreadPriority (nativeHandle, 16))
|
||||
{
|
||||
OSSleepTicks (OSMillisecondsToTicks (16));
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Underlying thread
|
||||
|
Loading…
Reference in New Issue
Block a user