Compare commits

...

7 Commits

Author SHA1 Message Date
Maschell b32f397969 Fix logging 2024-04-27 12:25:32 +02:00
Maschell 67162682bc Fix version 2024-04-27 12:25:22 +02:00
Maschell de4adc89e6 Update Dockerfile 2024-04-27 12:16:12 +02:00
Maschell dd2bc92243 Use stat from dirent* if possible 2024-04-27 12:15:30 +02:00
Maschell af6febd951 Bump softprops/action-gh-release from 3 to 4 2024-04-27 12:14:10 +02:00
Maschell 172030a254 Bump actions/checkout from 3 to 4 2024-04-27 12:13:53 +02:00
Maschell 792e138372 Add dependabot.yml 2024-04-27 12:13:27 +02:00
11 changed files with 160 additions and 165 deletions

10
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,10 @@
version: 2
updates:
- package-ecosystem: "docker"
directory: "/"
schedule:
interval: "daily"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"

View File

@ -9,7 +9,7 @@ jobs:
clang-format:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: clang-format
run: |
docker run --rm -v ${PWD}:/src ghcr.io/wiiu-env/clang-format:13.0.0-2 -r ./source ./include
@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-22.04
needs: clang-format
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: create version.h
run: |
git_hash=$(git rev-parse --short "$GITHUB_SHA")
@ -48,7 +48,7 @@ jobs:
- name: zip artifact
run: zip -r ${{ env.REPOSITORY_NAME }}_${{ env.DATETIME }}.zip *.wps
- name: Create Release
uses: "softprops/action-gh-release@v1"
uses: "softprops/action-gh-release@v2"
with:
tag_name: ${{ env.REPOSITORY_NAME }}-${{ env.DATETIME }}
draft: false

View File

@ -6,7 +6,7 @@ jobs:
clang-format:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: clang-format
run: |
docker run --rm -v ${PWD}:/src ghcr.io/wiiu-env/clang-format:13.0.0-2 -r ./source ./include
@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-22.04
needs: clang-format
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: create version.h
run: |
git_hash=$(git rev-parse --short "${{ github.event.pull_request.head.sha }}")

View File

@ -1,6 +1,6 @@
FROM ghcr.io/wiiu-env/devkitppc:20231112
FROM ghcr.io/wiiu-env/devkitppc:20240423
COPY --from=ghcr.io/wiiu-env/wiiupluginsystem:0.8.0-dev-20240302-3b5cc2f /artifacts $DEVKITPRO
COPY --from=ghcr.io/wiiu-env/wiiupluginsystem:20240425 /artifacts $DEVKITPRO
COPY --from=ghcr.io/wiiu-env/libmocha:20231127 /artifacts $DEVKITPRO
WORKDIR project

View File

@ -27,7 +27,7 @@
/// \brief Log level
enum LogLevel
{
DEBUG,
DEBUGLOG,
INFO,
ERROR,
COMMAND,

View File

@ -31,6 +31,9 @@ public:
}
mDir = {};
snprintf (mDir.d_name, sizeof (mDir.d_name), "%s", mCurIterator->c_str ());
#ifdef _DIRENT_HAVE_D_STAT
mDir.d_stat.st_mode = _IFDIR;
#endif
mCurIterator++;
mDirPtr.position++;
return &mDir;

View File

@ -1637,44 +1637,6 @@ void FtpSession::sendResponse (std::string_view const response_)
m_responseBuffer.markUsed (response_.size ());
}
#ifdef __WIIU__
#ifndef FSA_DIRITER_MAGIC
#define FSA_DIRITER_MAGIC 0x77696975
#endif
// TODO: make this less hacky. Ideally this should be handled by newlib.
typedef struct
{
uint32_t magic;
FSADirectoryHandle fd;
FSADirectoryEntry entry_data;
// Some fields are missing here!!!!
} __wut_fsa_dir_incomplete_t;
extern "C" void __wut_fsa_translate_stat (FSAClientHandle clientHandle,
FSStat *fsStat,
ino_t ino,
struct stat *posStat);
static bool __wut_fsa_get_stat_from_dir (DIR *dp, struct stat *posStat)
{
if (dp == NULL || dp->dirData == NULL || dp->dirData->dirStruct == NULL || posStat == NULL)
{
return false;
}
auto const magic = *(uint32_t *)(dp->dirData->dirStruct);
if (magic == FSA_DIRITER_MAGIC)
{
__wut_fsa_dir_incomplete_t *dir = (__wut_fsa_dir_incomplete_t *)dp->dirData->dirStruct;
__wut_fsa_translate_stat (0, &dir->entry_data.info, 0, posStat);
return true;
}
return false;
}
#endif
bool FtpSession::listTransfer ()
{
// check if we sent all available data
@ -1730,114 +1692,20 @@ bool FtpSession::listTransfer ()
{
// build the path
auto const fullPath = buildPath (m_lwd, dent->d_name);
struct stat st = {};
#ifdef __WIIU__
auto const dp = static_cast<DIR *> (m_dir);
if (__wut_fsa_get_stat_from_dir (dp, &st))
{
// success!
}
else
{ // fallback to lstat
#elifdef __3DS__
// the sdmc directory entry already has the type and size, so no need to do a slow stat
auto const dp = static_cast<DIR *> (m_dir);
auto const magic = *reinterpret_cast<u32 *> (dp->dirData->dirStruct);
if (magic == ARCHIVE_DIRITER_MAGIC)
{
auto const dir = reinterpret_cast<archive_dir_t const *> (dp->dirData->dirStruct);
auto const entry = &dir->entry_data[dir->index];
if (entry->attributes & FS_ATTRIBUTE_DIRECTORY)
st.st_mode = S_IFDIR | S_IRUSR | S_IRGRP | S_IROTH;
else
st.st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH;
if (!(entry->attributes & FS_ATTRIBUTE_READ_ONLY))
st.st_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
st.st_size = entry->fileSize;
st.st_mtime = 0;
bool getmtime = true;
if (m_xferDirMode == XferDirMode::MLSD || m_xferDirMode == XferDirMode::MLST)
{
if (!m_mlstModify)
getmtime = false;
}
else if (m_xferDirMode == XferDirMode::NLST)
getmtime = false;
{
auto const lock = m_config.lockGuard ();
if (!m_config.getMTime ())
getmtime = false;
}
if (getmtime)
{
std::uint64_t mtime = 0;
auto const rc = archive_getmtime (fullPath.c_str (), &mtime);
if (rc != 0)
error ("sdmc_getmtime %s 0x%lx\n", fullPath.c_str (), rc);
else
st.st_mtime = mtime;
}
}
else
{
#endif
// lstat the entry
if (IOAbstraction::lstat (fullPath.c_str (), &st) != 0)
{
#ifndef __SWITCH__
sendResponse ("550 %s\r\n", std::strerror (errno));
setState (State::COMMAND, true, true);
return false;
auto const path = encodePath (dent->d_name);
#ifdef _DIRENT_HAVE_D_STAT
auto const rc = fillDirent (dent->d_stat, path);
#else
// probably archive bit set; list name with dummy stats
std::memset (&st, 0, sizeof (st));
error ("%s: type %u\n", dent->d_name, dent->d_type);
switch (dent->d_type)
{
case DT_BLK:
st.st_mode = S_IFBLK;
break;
case DT_CHR:
st.st_mode = S_IFCHR;
break;
case DT_DIR:
st.st_mode = S_IFDIR;
break;
case DT_FIFO:
st.st_mode = S_IFIFO;
break;
case DT_LNK:
st.st_mode = S_IFLNK;
break;
case DT_REG:
case DT_UNKNOWN:
st.st_mode = S_IFREG;
break;
case DT_SOCK:
st.st_mode = S_IFSOCK;
break;
}
#endif
}
#if defined(__WIIU__) || defined(__3DS__)
struct stat st = {};
// lstat the entry
if (IOAbstraction::lstat (fullPath.c_str (), &st) != 0)
{
sendResponse ("550 %s\r\n", std::strerror (errno));
setState (State::COMMAND, true, true);
return false;
}
auto const rc = fillDirent (st, path);
#endif
auto const path = encodePath (dent->d_name);
auto const rc = fillDirent (st, path);
if (rc != 0)
{
sendResponse ("425 %s\r\n", std::strerror (errno));
@ -2343,7 +2211,7 @@ void FtpSession::PASV (char const *args_)
ephemeralPort = 5001;
addr.sin_port = htons (ephemeralPort++);
#else
addr.sin_port = htons (0);
addr.sin_port = htons (0);
#endif
// bind to the address

View File

@ -50,7 +50,7 @@ bool s_logUpdated = true;
/// \brief Message prefix
static char const *const s_prefix[] = {
[DEBUG] = "[DEBUG]",
[DEBUGLOG] = "[DEBUG]",
[INFO] = "[INFO]",
[ERROR] = "[ERROR]",
[COMMAND] = "[COMMAND]",
@ -114,7 +114,7 @@ void drawLog ()
#ifdef CLASSIC
char const *const s_colors[] = {
[DEBUG] = "\x1b[33;1m", // yellow
[DEBUGLOG] = "\x1b[33;1m", // yellow
[INFO] = "\x1b[37;1m", // white
[ERROR] = "\x1b[31;1m", // red
[COMMAND] = "\x1b[32;1m", // green
@ -204,7 +204,7 @@ void debug (char const *const fmt_, ...)
va_list ap;
va_start (ap, fmt_);
addLog (DEBUG, fmt_, ap);
addLog (DEBUGLOG, fmt_, ap);
va_end (ap);
#endif
}

42
source/wiiu/logger.c Normal file
View File

@ -0,0 +1,42 @@
#ifdef DEBUG
#include <stdint.h>
#include <whb/log_cafe.h>
#include <whb/log_module.h>
#include <whb/log_udp.h>
uint32_t moduleLogInit = false;
uint32_t cafeLogInit = false;
uint32_t udpLogInit = false;
#endif // DEBUG
void initLogging ()
{
#ifdef DEBUG
if (!(moduleLogInit = WHBLogModuleInit ()))
{
cafeLogInit = WHBLogCafeInit ();
udpLogInit = WHBLogUdpInit ();
}
#endif // DEBUG
}
void deinitLogging ()
{
#ifdef DEBUG
if (moduleLogInit)
{
WHBLogModuleDeinit ();
moduleLogInit = false;
}
if (cafeLogInit)
{
WHBLogCafeDeinit ();
cafeLogInit = false;
}
if (udpLogInit)
{
WHBLogUdpDeinit ();
udpLogInit = false;
}
#endif // DEBUG
}

67
source/wiiu/logger.h Normal file
View File

@ -0,0 +1,67 @@
#pragma once
#include <coreinit/debug.h>
#include <string.h>
#include <whb/log.h>
#ifdef __cplusplus
extern "C" {
#endif
#define LOG_APP_TYPE "P"
#define LOG_APP_NAME "homebrew_on_menu"
#define __FILENAME_X__ (strrchr (__FILE__, '\\') ? strrchr (__FILE__, '\\') + 1 : __FILE__)
#define __FILENAME__ (strrchr (__FILE__, '/') ? strrchr (__FILE__, '/') + 1 : __FILENAME_X__)
#define LOG(LOG_FUNC, FMT, ARGS...) LOG_EX (LOG_FUNC, "", "", FMT, ##ARGS)
#define LOG_EX(LOG_FUNC, LOG_LEVEL, LINE_END, FMT, ARGS...) \
do \
{ \
LOG_FUNC ("[(%s)%18s][%23s]%30s@L%04d: " LOG_LEVEL "" FMT "" LINE_END, \
LOG_APP_TYPE, \
LOG_APP_NAME, \
__FILENAME__, \
__FUNCTION__, \
__LINE__, \
##ARGS); \
} while (0)
#ifdef DEBUG
#ifdef VERBOSE_DEBUG
#define DEBUG_FUNCTION_LINE_VERBOSE(FMT, ARGS...) LOG (WHBLogPrintf, FMT, ##ARGS)
#else
#define DEBUG_FUNCTION_LINE_VERBOSE(FMT, ARGS...) while (0)
#endif
#define DEBUG_FUNCTION_LINE(FMT, ARGS...) LOG (WHBLogPrintf, FMT, ##ARGS)
#define DEBUG_FUNCTION_LINE_WRITE(FMT, ARGS...) LOG (WHBLogWritef, FMT, ##ARGS)
#define DEBUG_FUNCTION_LINE_ERR(FMT, ARGS...) LOG_EX (WHBLogPrintf, "##ERROR## ", "", FMT, ##ARGS)
#define DEBUG_FUNCTION_LINE_WARN(FMT, ARGS...) LOG_EX (WHBLogPrintf, "##WARN ## ", "", FMT, ##ARGS)
#define DEBUG_FUNCTION_LINE_INFO(FMT, ARGS...) LOG_EX (WHBLogPrintf, "##INFO ## ", "", FMT, ##ARGS)
#else
#define DEBUG_FUNCTION_LINE_VERBOSE(FMT, ARGS...) while (0)
#define DEBUG_FUNCTION_LINE(FMT, ARGS...) while (0)
#define DEBUG_FUNCTION_LINE_WRITE(FMT, ARGS...) while (0)
#define DEBUG_FUNCTION_LINE_ERR(FMT, ARGS...) LOG_EX (OSReport, "##ERROR## ", "\n", FMT, ##ARGS)
#define DEBUG_FUNCTION_LINE_WARN(FMT, ARGS...) LOG_EX (OSReport, "##WARN ## ", "\n", FMT, ##ARGS)
#define DEBUG_FUNCTION_LINE_INFO(FMT, ARGS...) LOG_EX (OSReport, "##INFO ## ", "\n", FMT, ##ARGS)
#endif
void initLogging ();
void deinitLogging ();
#ifdef __cplusplus
}
#endif

View File

@ -24,6 +24,7 @@
#include "IOAbstraction.h"
#include "ftpServer.h"
#include "log.h"
#include "logger.h"
#include <mocha/mocha.h>
#include <nn/ac.h>
@ -40,7 +41,7 @@
#ifndef CLASSIC
#error "Wii U must be built in classic mode"
#endif
#define VERSION "v0.4.1"
#define VERSION "v0.4.0"
#define VERSION_FULL VERSION VERSION_EXTRA
WUPS_PLUGIN_NAME ("ftpiiu");
@ -86,7 +87,8 @@ MochaUtilsStatus MountWrapper (const char *mount, const char *dev, const char *m
}
else
{
error ("Failed to mount %s: %s [%d]", mount, Mocha_GetStatusStr (res), res);
DEBUG_FUNCTION_LINE_ERR (
"Failed to mount %s: %s [%d]", mount, Mocha_GetStatusStr (res), res);
}
return res;
}
@ -169,7 +171,8 @@ void start_server ()
}
else
{
OSReport ("Failed to init libmocha: %s [%d]\n", Mocha_GetStatusStr (res), res);
DEBUG_FUNCTION_LINE_ERR (
"Failed to init libmocha: %s [%d]\n", Mocha_GetStatusStr (res), res);
}
server = FtpServer::create ();
@ -209,7 +212,7 @@ static void gFTPServerRunningChanged (ConfigItemBoolean *item, bool newValue)
auto res = WUPSStorageAPI::Store (FTPIIU_ENABLED_STRING, sFTPServerEnabled);
if (res != WUPS_STORAGE_ERROR_SUCCESS)
{
OSReport ("Failed to store gFTPServerEnabled: %s (%d)\n",
DEBUG_FUNCTION_LINE_ERR ("Failed to store gFTPServerEnabled: %s (%d)\n",
WUPSStorageAPI::GetStatusStr (res).data (),
res);
}
@ -232,7 +235,7 @@ static void gSystemFilesAllowedChanged (ConfigItemBoolean *item, bool newValue)
auto res = WUPSStorageAPI::Store (SYSTEM_FILES_ALLOWED_STRING, sSystemFilesAllowed);
if (res != WUPS_STORAGE_ERROR_SUCCESS)
{
OSReport ("Failed to store gSystemFilesAllowed: %s (%d)\n",
DEBUG_FUNCTION_LINE_ERR ("Failed to store gSystemFilesAllowed: %s (%d)\n",
WUPSStorageAPI::GetStatusStr (res).data (),
res);
}
@ -300,6 +303,7 @@ INITIALIZE_PLUGIN ()
if (WUPSConfigAPI_Init (configOptions, ConfigMenuOpenedCallback, ConfigMenuClosedCallback) !=
WUPSCONFIG_API_RESULT_SUCCESS)
{
DEBUG_FUNCTION_LINE_ERR ("Failed to init config api");
OSFatal ("ftpiiu plugin: Failed to init config api");
}
@ -308,7 +312,7 @@ INITIALIZE_PLUGIN ()
FTPIIU_ENABLED_STRING, sFTPServerEnabled, DEFAULT_FTPIIU_ENABLED_VALUE)) !=
WUPS_STORAGE_ERROR_SUCCESS)
{
OSReport ("ftpiiu plugin: Failed to get or create item \"%s\": %s (%d)\n",
DEBUG_FUNCTION_LINE_ERR ("Failed to get or create item \"%s\": %s (%d)\n",
FTPIIU_ENABLED_STRING,
WUPSStorageAPI_GetStatusStr (err),
err);
@ -317,7 +321,7 @@ INITIALIZE_PLUGIN ()
sSystemFilesAllowed,
DEFAULT_SYSTEM_FILES_ALLOWED_VALUE)) != WUPS_STORAGE_ERROR_SUCCESS)
{
OSReport ("ftpiiu plugin: Failed to get or create item \"%s\": %s (%d)\n",
DEBUG_FUNCTION_LINE_ERR ("Failed to get or create item \"%s\": %s (%d)\n",
SYSTEM_FILES_ALLOWED_STRING,
WUPSStorageAPI_GetStatusStr (err),
err);
@ -325,9 +329,8 @@ INITIALIZE_PLUGIN ()
if ((err = WUPSStorageAPI::SaveStorage ()) != WUPS_STORAGE_ERROR_SUCCESS)
{
OSReport ("ftpiiu plugin: Failed to save storage: %s (%d)\n",
WUPSStorageAPI_GetStatusStr (err),
err);
DEBUG_FUNCTION_LINE_ERR (
"Failed to save storage: %s (%d)\n", WUPSStorageAPI_GetStatusStr (err), err);
}
}
@ -343,6 +346,7 @@ void wiiu_init ()
ON_APPLICATION_START ()
{
initLogging ();
nn::ac::Initialize ();
nn::ac::ConnectAsync ();
@ -352,6 +356,7 @@ ON_APPLICATION_START ()
ON_APPLICATION_ENDS ()
{
stop_server ();
deinitLogging ();
}
bool platform::init ()