mirror of
https://github.com/wiiu-env/ftpiiu_plugin.git
synced 2024-12-23 03:11:49 +01:00
Formatting and cleanup
This commit is contained in:
parent
f4dd784456
commit
9f784cbf1b
@ -1,50 +1,42 @@
|
|||||||
#include "BackgroundThread.hpp"
|
#include "BackgroundThread.hpp"
|
||||||
#include <malloc.h>
|
#include <cstring>
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <coreinit/cache.h>
|
|
||||||
|
|
||||||
#include <utils/logger.h>
|
|
||||||
|
|
||||||
#include "ftp.h"
|
#include "ftp.h"
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
|
|
||||||
BackgroundThread * BackgroundThread::instance = nullptr;
|
BackgroundThread *BackgroundThread::instance = nullptr;
|
||||||
|
|
||||||
BackgroundThread::BackgroundThread(): BackgroundThreadWrapper(BackgroundThread::getPriority()) {
|
BackgroundThread::BackgroundThread() : BackgroundThreadWrapper(BackgroundThread::getPriority()) {
|
||||||
DEBUG_FUNCTION_LINE("Create new Server");
|
DEBUG_FUNCTION_LINE("Start FTP Server");
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
this->serverSocket = create_server(PORT);
|
this->serverSocket = create_server(PORT);
|
||||||
DCFlushRange(&(this->serverSocket), 4);
|
DCFlushRange(&(this->serverSocket), 4);
|
||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
DEBUG_FUNCTION_LINE("handle %d", this->serverSocket);
|
|
||||||
CThread::resumeThread();
|
CThread::resumeThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
BackgroundThread::~BackgroundThread() {
|
BackgroundThread::~BackgroundThread() {
|
||||||
DEBUG_FUNCTION_LINE("Clean up FTP");
|
DEBUG_FUNCTION_LINE("Shutting down FTP Server");
|
||||||
if(this->serverSocket != -1){
|
if (this->serverSocket != -1) {
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
cleanup_ftp();
|
cleanup_ftp();
|
||||||
network_close(this->serverSocket);
|
network_close(this->serverSocket);
|
||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
this->serverSocket = -1;
|
this->serverSocket = -1;
|
||||||
}
|
}
|
||||||
DEBUG_FUNCTION_LINE("Cleaned up FTP");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL BackgroundThread::whileLoop() {
|
BOOL BackgroundThread::whileLoop() {
|
||||||
if(this->serverSocket != -1){
|
if (this->serverSocket != -1) {
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
network_down = process_ftp_events(this->serverSocket);
|
network_down = process_ftp_events(this->serverSocket);
|
||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
if(network_down) {
|
if (network_down) {
|
||||||
DEBUG_FUNCTION_LINE("Network is down %d", this->serverSocket);
|
DEBUG_FUNCTION_LINE("Network is down %d", this->serverSocket);
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
cleanup_ftp();
|
cleanup_ftp();
|
||||||
network_close(this->serverSocket);
|
network_close(this->serverSocket);
|
||||||
this->serverSocket = -1;
|
this->serverSocket = -1;
|
||||||
DCFlushRange(&(this->serverSocket), 4);
|
DCFlushRange(&(this->serverSocket), 4);
|
||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,50 +1,50 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "utils/BackgroundThreadWrapper.hpp"
|
#include "utils/BackgroundThreadWrapper.hpp"
|
||||||
#include <coreinit/cache.h>
|
#include <coreinit/cache.h>
|
||||||
#include "utils/logger.h"
|
#include "utils/logger.h"
|
||||||
|
|
||||||
#define PORT 21
|
#define PORT 21
|
||||||
|
|
||||||
class BackgroundThread: BackgroundThreadWrapper {
|
class BackgroundThread : BackgroundThreadWrapper {
|
||||||
public:
|
public:
|
||||||
static BackgroundThread *getInstance() {
|
static BackgroundThread *getInstance() {
|
||||||
DCFlushRange(&instance, sizeof(instance));
|
DCFlushRange(&instance, sizeof(BackgroundThread));
|
||||||
ICInvalidateRange(&instance, sizeof(instance));
|
ICInvalidateRange(&instance, sizeof(BackgroundThread));
|
||||||
if(instance == NULL) {
|
if (instance == nullptr) {
|
||||||
instance = new BackgroundThread();
|
instance = new BackgroundThread();
|
||||||
DCFlushRange(&instance, sizeof(instance));
|
DCFlushRange(&instance, sizeof(BackgroundThread));
|
||||||
ICInvalidateRange(&instance, sizeof(instance));
|
ICInvalidateRange(&instance, sizeof(BackgroundThread));
|
||||||
}
|
}
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void destroyInstance() {
|
static void destroyInstance() {
|
||||||
DCFlushRange(&instance, sizeof(instance));
|
DCFlushRange(&instance, sizeof(BackgroundThread));
|
||||||
ICInvalidateRange(&instance, sizeof(instance));
|
ICInvalidateRange(&instance, sizeof(BackgroundThread));
|
||||||
DEBUG_FUNCTION_LINE("Instance is %08X\n", instance);
|
DEBUG_FUNCTION_LINE("Instance is %08X\n", instance);
|
||||||
OSSleepTicks(OSSecondsToTicks(1));
|
OSSleepTicks(OSSecondsToTicks(1));
|
||||||
if(instance != NULL) {
|
if (instance != nullptr) {
|
||||||
delete instance;
|
delete instance;
|
||||||
instance = NULL;
|
instance = nullptr;
|
||||||
DCFlushRange(&instance, sizeof(instance));
|
DCFlushRange(&instance, sizeof(BackgroundThread));
|
||||||
ICInvalidateRange(&instance, sizeof(instance));
|
ICInvalidateRange(&instance, sizeof(BackgroundThread));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BackgroundThread();
|
BackgroundThread();
|
||||||
|
|
||||||
virtual ~BackgroundThread();
|
~BackgroundThread() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static int32_t getPriority() {
|
static int32_t getPriority() {
|
||||||
return 16;
|
return 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual BOOL whileLoop();
|
BOOL whileLoop() override;
|
||||||
|
|
||||||
static BackgroundThread * instance;
|
static BackgroundThread *instance;
|
||||||
|
|
||||||
int serverSocket = -1;
|
int serverSocket = -1;
|
||||||
int network_down = 0;
|
int network_down = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
79
src/ftp.c
79
src/ftp.c
@ -42,7 +42,7 @@ misrepresented as being the original software.
|
|||||||
#include "net.h"
|
#include "net.h"
|
||||||
#include "vrt.h"
|
#include "vrt.h"
|
||||||
|
|
||||||
#define UNUSED __attribute__((unused))
|
#define UNUSED __attribute__((unused))
|
||||||
|
|
||||||
#define FTP_BUFFER_SIZE 1024
|
#define FTP_BUFFER_SIZE 1024
|
||||||
#define MAX_CLIENTS 5
|
#define MAX_CLIENTS 5
|
||||||
@ -56,7 +56,7 @@ static uint8_t num_clients = 0;
|
|||||||
static uint16_t passive_port = 1024;
|
static uint16_t passive_port = 1024;
|
||||||
static char *password = NULL;
|
static char *password = NULL;
|
||||||
|
|
||||||
void console_printf(const char *format, ...){
|
void console_printf(const char *format, ...) {
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef int32_t (*data_connection_callback)(int32_t data_socket, void *arg);
|
typedef int32_t (*data_connection_callback)(int32_t data_socket, void *arg);
|
||||||
@ -76,13 +76,15 @@ struct client_struct {
|
|||||||
bool data_connection_connected;
|
bool data_connection_connected;
|
||||||
data_connection_callback data_callback;
|
data_connection_callback data_callback;
|
||||||
void *data_connection_callback_arg;
|
void *data_connection_callback_arg;
|
||||||
|
|
||||||
void (*data_connection_cleanup)(void *arg);
|
void (*data_connection_cleanup)(void *arg);
|
||||||
|
|
||||||
uint64_t data_connection_timer;
|
uint64_t data_connection_timer;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct client_struct client_t;
|
typedef struct client_struct client_t;
|
||||||
|
|
||||||
static client_t *clients[MAX_CLIENTS] = { NULL };
|
static client_t *clients[MAX_CLIENTS] = {NULL};
|
||||||
|
|
||||||
void set_ftp_password(char *new_password) {
|
void set_ftp_password(char *new_password) {
|
||||||
if (password)
|
if (password)
|
||||||
@ -92,14 +94,14 @@ void set_ftp_password(char *new_password) {
|
|||||||
if (!password)
|
if (!password)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
strcpy((char *)password, new_password);
|
strcpy((char *) password, new_password);
|
||||||
} else {
|
} else {
|
||||||
password = NULL;
|
password = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool compare_ftp_password(char *password_attempt) {
|
static bool compare_ftp_password(char *password_attempt) {
|
||||||
return !password || !strcmp((char *)password, password_attempt);
|
return !password || !strcmp((char *) password, password_attempt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -107,7 +109,7 @@ static bool compare_ftp_password(char *password_attempt) {
|
|||||||
*/
|
*/
|
||||||
static int32_t write_reply(client_t *client, uint16_t code, char *msg) {
|
static int32_t write_reply(client_t *client, uint16_t code, char *msg) {
|
||||||
uint32_t msglen = 4 + strlen(msg) + CRLF_LENGTH;
|
uint32_t msglen = 4 + strlen(msg) + CRLF_LENGTH;
|
||||||
char * msgbuf = (char *) malloc(msglen + 1);
|
char *msgbuf = (char *) malloc(msglen + 1);
|
||||||
if (msgbuf == NULL)
|
if (msgbuf == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
sprintf(msgbuf, "%u %s\r\n", code, msg);
|
sprintf(msgbuf, "%u %s\r\n", code, msg);
|
||||||
@ -197,7 +199,7 @@ static int32_t ftp_SYST(client_t *client, char *rest UNUSED) {
|
|||||||
|
|
||||||
static int32_t ftp_TYPE(client_t *client, char *rest) {
|
static int32_t ftp_TYPE(client_t *client, char *rest) {
|
||||||
char representation_type[FTP_BUFFER_SIZE], param[FTP_BUFFER_SIZE];
|
char representation_type[FTP_BUFFER_SIZE], param[FTP_BUFFER_SIZE];
|
||||||
char *args[] = { representation_type, param };
|
char *args[] = {representation_type, param};
|
||||||
uint32_t num_args = split(rest, ' ', 1, args);
|
uint32_t num_args = split(rest, ' ', 1, args);
|
||||||
if (num_args == 0) {
|
if (num_args == 0) {
|
||||||
return write_reply(client, 501, "Syntax error in parameters.");
|
return write_reply(client, 501, "Syntax error in parameters.");
|
||||||
@ -231,7 +233,7 @@ static int32_t ftp_CWD(client_t *client, char *path) {
|
|||||||
int32_t result;
|
int32_t result;
|
||||||
if (!vrt_chdir(client->cwd, path)) {
|
if (!vrt_chdir(client->cwd, path)) {
|
||||||
result = write_reply(client, 250, "CWD command successful.");
|
result = write_reply(client, 250, "CWD command successful.");
|
||||||
} else {
|
} else {
|
||||||
result = write_reply(client, 550, strerror(errno));
|
result = write_reply(client, 550, strerror(errno));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -241,7 +243,7 @@ static int32_t ftp_CDUP(client_t *client, char *rest UNUSED) {
|
|||||||
int32_t result;
|
int32_t result;
|
||||||
if (!vrt_chdir(client->cwd, "..")) {
|
if (!vrt_chdir(client->cwd, "..")) {
|
||||||
result = write_reply(client, 250, "CDUP command successful.");
|
result = write_reply(client, 250, "CDUP command successful.");
|
||||||
} else {
|
} else {
|
||||||
result = write_reply(client, 550, strerror(errno));
|
result = write_reply(client, 550, strerror(errno));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -287,7 +289,7 @@ static int32_t ftp_RNTO(client_t *client, char *path) {
|
|||||||
} else {
|
} else {
|
||||||
result = write_reply(client, 550, strerror(
|
result = write_reply(client, 550, strerror(
|
||||||
|
|
||||||
errno));
|
errno));
|
||||||
}
|
}
|
||||||
*client->pending_rename = '\0';
|
*client->pending_rename = '\0';
|
||||||
return result;
|
return result;
|
||||||
@ -317,7 +319,7 @@ static int32_t ftp_PASV(client_t *client, char *rest UNUSED) {
|
|||||||
bindAddress.sin_port = htons(passive_port++); // XXX: BUG: This will overflow eventually, with interesting results...
|
bindAddress.sin_port = htons(passive_port++); // XXX: BUG: This will overflow eventually, with interesting results...
|
||||||
bindAddress.sin_addr.s_addr = htonl(INADDR_ANY);
|
bindAddress.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
int32_t result;
|
int32_t result;
|
||||||
if ((result = network_bind(client->passive_socket, (struct sockaddr *)&bindAddress, sizeof(bindAddress))) < 0) {
|
if ((result = network_bind(client->passive_socket, (struct sockaddr *) &bindAddress, sizeof(bindAddress))) < 0) {
|
||||||
close_passive_socket(client);
|
close_passive_socket(client);
|
||||||
return write_reply(client, 520, "Unable to bind listening socket.");
|
return write_reply(client, 520, "Unable to bind listening socket.");
|
||||||
}
|
}
|
||||||
@ -347,7 +349,7 @@ static int32_t ftp_PORT(client_t *client, char *portspec) {
|
|||||||
return write_reply(client, 501, "Syntax error in parameters.");
|
return write_reply(client, 501, "Syntax error in parameters.");
|
||||||
}
|
}
|
||||||
close_passive_socket(client);
|
close_passive_socket(client);
|
||||||
uint16_t port = ((p1 &0xff) << 8) | (p2 & 0xff);
|
uint16_t port = ((p1 & 0xff) << 8) | (p2 & 0xff);
|
||||||
client->address.sin_addr = sin_addr;
|
client->address.sin_addr = sin_addr;
|
||||||
client->address.sin_port = htons(port);
|
client->address.sin_port = htons(port);
|
||||||
console_printf("Set client address to %s:%u\n", addr_str, port);
|
console_printf("Set client address to %s:%u\n", addr_str, port);
|
||||||
@ -367,7 +369,7 @@ static int32_t prepare_data_connection_active(client_t *client, data_connection_
|
|||||||
bindAddress.sin_port = htons(SRC_PORT);
|
bindAddress.sin_port = htons(SRC_PORT);
|
||||||
bindAddress.sin_addr.s_addr = htonl(INADDR_ANY);
|
bindAddress.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
int32_t result;
|
int32_t result;
|
||||||
if ((result = network_bind(data_socket, (struct sockaddr *)&bindAddress, sizeof(bindAddress))) < 0) {
|
if ((result = network_bind(data_socket, (struct sockaddr *) &bindAddress, sizeof(bindAddress))) < 0) {
|
||||||
network_close(data_socket);
|
network_close(data_socket);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -389,7 +391,7 @@ static int32_t prepare_data_connection(client_t *client, void *callback, void *a
|
|||||||
data_connection_handler handler = prepare_data_connection_active;
|
data_connection_handler handler = prepare_data_connection_active;
|
||||||
if (client->passive_socket >= 0)
|
if (client->passive_socket >= 0)
|
||||||
handler = prepare_data_connection_passive;
|
handler = prepare_data_connection_passive;
|
||||||
result = handler(client, (data_connection_callback)callback, arg);
|
result = handler(client, (data_connection_callback) callback, arg);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
result = write_reply(client, 520, "Closing data connection, error occurred during transfer.");
|
result = write_reply(client, 520, "Closing data connection, error occurred during transfer.");
|
||||||
} else {
|
} else {
|
||||||
@ -409,7 +411,7 @@ static int32_t send_nlst(int32_t data_socket, DIR_P *iter) {
|
|||||||
struct dirent *dirent = NULL;
|
struct dirent *dirent = NULL;
|
||||||
while ((dirent = vrt_readdir(iter)) != 0) {
|
while ((dirent = vrt_readdir(iter)) != 0) {
|
||||||
size_t end_index = strlen(dirent->d_name);
|
size_t end_index = strlen(dirent->d_name);
|
||||||
if(end_index + 2 >= MAXPATHLEN)
|
if (end_index + 2 >= MAXPATHLEN)
|
||||||
continue;
|
continue;
|
||||||
strcpy(filename, dirent->d_name);
|
strcpy(filename, dirent->d_name);
|
||||||
filename[end_index] = CRLF[0];
|
filename[end_index] = CRLF[0];
|
||||||
@ -433,7 +435,7 @@ static int32_t send_list(int32_t data_socket, DIR_P *iter) {
|
|||||||
while ((dirent = vrt_readdir(iter)) != 0) {
|
while ((dirent = vrt_readdir(iter)) != 0) {
|
||||||
|
|
||||||
snprintf(filename, sizeof(filename), "%s/%s", iter->path, dirent->d_name);
|
snprintf(filename, sizeof(filename), "%s/%s", iter->path, dirent->d_name);
|
||||||
if(stat(filename, &st) == 0) {
|
if (stat(filename, &st) == 0) {
|
||||||
mtime = st.st_mtime;
|
mtime = st.st_mtime;
|
||||||
size = st.st_size;
|
size = st.st_size;
|
||||||
} else {
|
} else {
|
||||||
@ -472,7 +474,7 @@ static int32_t ftp_LIST(client_t *client, char *path) {
|
|||||||
// handle buggy clients that use "LIST -aL" or similar, at the expense of breaking paths that begin with '-'
|
// handle buggy clients that use "LIST -aL" or similar, at the expense of breaking paths that begin with '-'
|
||||||
char flags[FTP_BUFFER_SIZE];
|
char flags[FTP_BUFFER_SIZE];
|
||||||
char rest[FTP_BUFFER_SIZE];
|
char rest[FTP_BUFFER_SIZE];
|
||||||
char *args[] = { flags, rest };
|
char *args[] = {flags, rest};
|
||||||
split(path, ' ', 1, args);
|
split(path, ' ', 1, args);
|
||||||
path = rest;
|
path = rest;
|
||||||
}
|
}
|
||||||
@ -480,8 +482,8 @@ static int32_t ftp_LIST(client_t *client, char *path) {
|
|||||||
path = ".";
|
path = ".";
|
||||||
}
|
}
|
||||||
|
|
||||||
if(path && client->cwd) {
|
if (path && client->cwd) {
|
||||||
if(strcmp(path, ".") == 0 && strcmp(client->cwd, "/") == 0) {
|
if (strcmp(path, ".") == 0 && strcmp(client->cwd, "/") == 0) {
|
||||||
UnmountVirtualPaths();
|
UnmountVirtualPaths();
|
||||||
MountVirtualDevices();
|
MountVirtualDevices();
|
||||||
}
|
}
|
||||||
@ -628,7 +630,7 @@ typedef int32_t (*ftp_command_handler)(client_t *client, char *args);
|
|||||||
|
|
||||||
static int32_t dispatch_to_handler(client_t *client, char *cmd_line, const char **commands, const ftp_command_handler *handlers) {
|
static int32_t dispatch_to_handler(client_t *client, char *cmd_line, const char **commands, const ftp_command_handler *handlers) {
|
||||||
char cmd[FTP_BUFFER_SIZE], rest[FTP_BUFFER_SIZE];
|
char cmd[FTP_BUFFER_SIZE], rest[FTP_BUFFER_SIZE];
|
||||||
char *args[] = { cmd, rest };
|
char *args[] = {cmd, rest};
|
||||||
split(cmd_line, ' ', 1, args);
|
split(cmd_line, ' ', 1, args);
|
||||||
int32_t i;
|
int32_t i;
|
||||||
for (i = 0; commands[i]; i++) {
|
for (i = 0; commands[i]; i++) {
|
||||||
@ -638,8 +640,9 @@ static int32_t dispatch_to_handler(client_t *client, char *cmd_line, const char
|
|||||||
return handlers[i](client, rest);
|
return handlers[i](client, rest);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *site_commands[] = { "LOADER", "CLEAR", "CHMOD", "PASSWD", "NOPASSWD", "EJECT", "MOUNT", "UNMOUNT", "LOAD", NULL };
|
static const char *site_commands[] = {"LOADER", "CLEAR", "CHMOD", "PASSWD", "NOPASSWD", "EJECT", "MOUNT", "UNMOUNT", "LOAD", NULL};
|
||||||
static const ftp_command_handler site_handlers[] = { ftp_SITE_LOADER, ftp_SITE_CLEAR, ftp_SITE_CHMOD, ftp_SITE_PASSWD, ftp_SITE_NOPASSWD, ftp_SITE_EJECT, ftp_SITE_MOUNT, ftp_SITE_UNMOUNT, ftp_SITE_LOAD, ftp_SITE_UNKNOWN };
|
static const ftp_command_handler site_handlers[] = {ftp_SITE_LOADER, ftp_SITE_CLEAR, ftp_SITE_CHMOD, ftp_SITE_PASSWD, ftp_SITE_NOPASSWD, ftp_SITE_EJECT, ftp_SITE_MOUNT, ftp_SITE_UNMOUNT,
|
||||||
|
ftp_SITE_LOAD, ftp_SITE_UNKNOWN};
|
||||||
|
|
||||||
static int32_t ftp_SITE(client_t *client, char *cmd_line) {
|
static int32_t ftp_SITE(client_t *client, char *cmd_line) {
|
||||||
return dispatch_to_handler(client, cmd_line, site_commands, site_handlers);
|
return dispatch_to_handler(client, cmd_line, site_commands, site_handlers);
|
||||||
@ -661,22 +664,22 @@ static int32_t ftp_UNKNOWN(client_t *client, char *rest UNUSED) {
|
|||||||
return write_reply(client, 502, "Command not implemented.");
|
return write_reply(client, 502, "Command not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *unauthenticated_commands[] = { "USER", "PASS", "QUIT", "REIN", "NOOP", NULL };
|
static const char *unauthenticated_commands[] = {"USER", "PASS", "QUIT", "REIN", "NOOP", NULL};
|
||||||
static const ftp_command_handler unauthenticated_handlers[] = { ftp_USER, ftp_PASS, ftp_QUIT, ftp_REIN, ftp_NOOP, ftp_NEEDAUTH };
|
static const ftp_command_handler unauthenticated_handlers[] = {ftp_USER, ftp_PASS, ftp_QUIT, ftp_REIN, ftp_NOOP, ftp_NEEDAUTH};
|
||||||
|
|
||||||
static const char *authenticated_commands[] = {
|
static const char *authenticated_commands[] = {
|
||||||
"USER", "PASS", "LIST", "PWD", "CWD", "CDUP",
|
"USER", "PASS", "LIST", "PWD", "CWD", "CDUP",
|
||||||
"SIZE", "PASV", "PORT", "TYPE", "SYST", "MODE",
|
"SIZE", "PASV", "PORT", "TYPE", "SYST", "MODE",
|
||||||
"RETR", "STOR", "APPE", "REST", "DELE", "MKD",
|
"RETR", "STOR", "APPE", "REST", "DELE", "MKD",
|
||||||
"RMD", "RNFR", "RNTO", "NLST", "QUIT", "REIN",
|
"RMD", "RNFR", "RNTO", "NLST", "QUIT", "REIN",
|
||||||
"SITE", "NOOP", "ALLO", NULL
|
"SITE", "NOOP", "ALLO", NULL
|
||||||
};
|
};
|
||||||
static const ftp_command_handler authenticated_handlers[] = {
|
static const ftp_command_handler authenticated_handlers[] = {
|
||||||
ftp_USER, ftp_PASS, ftp_LIST, ftp_PWD, ftp_CWD, ftp_CDUP,
|
ftp_USER, ftp_PASS, ftp_LIST, ftp_PWD, ftp_CWD, ftp_CDUP,
|
||||||
ftp_SIZE, ftp_PASV, ftp_PORT, ftp_TYPE, ftp_SYST, ftp_MODE,
|
ftp_SIZE, ftp_PASV, ftp_PORT, ftp_TYPE, ftp_SYST, ftp_MODE,
|
||||||
ftp_RETR, ftp_STOR, ftp_APPE, ftp_REST, ftp_DELE, ftp_MKD,
|
ftp_RETR, ftp_STOR, ftp_APPE, ftp_REST, ftp_DELE, ftp_MKD,
|
||||||
ftp_DELE, ftp_RNFR, ftp_RNTO, ftp_NLST, ftp_QUIT, ftp_REIN,
|
ftp_DELE, ftp_RNFR, ftp_RNTO, ftp_NLST, ftp_QUIT, ftp_REIN,
|
||||||
ftp_SITE, ftp_NOOP, ftp_SUPERFLUOUS, ftp_UNKNOWN
|
ftp_SITE, ftp_NOOP, ftp_SUPERFLUOUS, ftp_UNKNOWN
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -746,7 +749,7 @@ static bool process_accept_events(int32_t server) {
|
|||||||
int32_t peer;
|
int32_t peer;
|
||||||
struct sockaddr_in client_address;
|
struct sockaddr_in client_address;
|
||||||
int32_t addrlen = sizeof(client_address);
|
int32_t addrlen = sizeof(client_address);
|
||||||
while ((peer = network_accept(server, (struct sockaddr *)&client_address, &addrlen)) != -EAGAIN) {
|
while ((peer = network_accept(server, (struct sockaddr *) &client_address, &addrlen)) != -EAGAIN) {
|
||||||
if (peer < 0) {
|
if (peer < 0) {
|
||||||
console_printf("Error accepting connection: [%i] %s\n", -peer, strerror(-peer));
|
console_printf("Error accepting connection: [%i] %s\n", -peer, strerror(-peer));
|
||||||
return false;
|
return false;
|
||||||
@ -805,13 +808,13 @@ static void process_data_events(client_t *client) {
|
|||||||
if (client->passive_socket >= 0) {
|
if (client->passive_socket >= 0) {
|
||||||
struct sockaddr_in data_peer_address;
|
struct sockaddr_in data_peer_address;
|
||||||
int32_t addrlen = sizeof(data_peer_address);
|
int32_t addrlen = sizeof(data_peer_address);
|
||||||
result = network_accept(client->passive_socket, (struct sockaddr *)&data_peer_address,&addrlen);
|
result = network_accept(client->passive_socket, (struct sockaddr *) &data_peer_address, &addrlen);
|
||||||
if (result >= 0) {
|
if (result >= 0) {
|
||||||
client->data_socket = result;
|
client->data_socket = result;
|
||||||
client->data_connection_connected = true;
|
client->data_connection_connected = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ((result = network_connect(client->data_socket, (struct sockaddr *)&client->address, sizeof(client->address))) < 0) {
|
if ((result = network_connect(client->data_socket, (struct sockaddr *) &client->address, sizeof(client->address))) < 0) {
|
||||||
if (result == -EINPROGRESS || result == -EALREADY)
|
if (result == -EINPROGRESS || result == -EALREADY)
|
||||||
result = -EAGAIN;
|
result = -EAGAIN;
|
||||||
if ((result != -EAGAIN) && (result != -EISCONN)) {
|
if ((result != -EAGAIN) && (result != -EISCONN)) {
|
||||||
@ -900,7 +903,7 @@ static void process_control_events(client_t *client) {
|
|||||||
}
|
}
|
||||||
console_printf("Received line longer than %u bytes, closing client.\n", FTP_BUFFER_SIZE - 1);
|
console_printf("Received line longer than %u bytes, closing client.\n", FTP_BUFFER_SIZE - 1);
|
||||||
|
|
||||||
recv_loop_end:
|
recv_loop_end:
|
||||||
cleanup_client(client);
|
cleanup_client(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,11 +29,15 @@ misrepresented as being the original software.
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C"{
|
extern "C"{
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
void accept_ftp_client(int32_t server);
|
void accept_ftp_client(int32_t server);
|
||||||
|
|
||||||
void set_ftp_password(char *new_password);
|
void set_ftp_password(char *new_password);
|
||||||
|
|
||||||
bool process_ftp_events(int32_t server);
|
bool process_ftp_events(int32_t server);
|
||||||
|
|
||||||
void cleanup_ftp();
|
void cleanup_ftp();
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
27
src/main.cpp
27
src/main.cpp
@ -8,7 +8,6 @@
|
|||||||
#include <coreinit/cache.h>
|
#include <coreinit/cache.h>
|
||||||
#include "utils/logger.h"
|
#include "utils/logger.h"
|
||||||
#include <whb/log_udp.h>
|
#include <whb/log_udp.h>
|
||||||
#include <whb/libmanager.h>
|
|
||||||
#include "virtualpath.h"
|
#include "virtualpath.h"
|
||||||
#include "BackgroundThread.hpp"
|
#include "BackgroundThread.hpp"
|
||||||
|
|
||||||
@ -27,15 +26,15 @@ uint32_t hostIpAddress = 0;
|
|||||||
int iosuhaxMount = 0;
|
int iosuhaxMount = 0;
|
||||||
int fsaFd = -1;
|
int fsaFd = -1;
|
||||||
|
|
||||||
BackgroundThread * thread = nullptr;
|
BackgroundThread *thread = nullptr;
|
||||||
|
|
||||||
/* Entry point */
|
/* Entry point */
|
||||||
ON_APPLICATION_START() {
|
ON_APPLICATION_START() {
|
||||||
nn::ac::Initialize();
|
nn::ac::Initialize();
|
||||||
nn::ac::ConnectAsync();
|
nn::ac::ConnectAsync();
|
||||||
nn::ac::GetAssignedAddress(&hostIpAddress);
|
nn::ac::GetAssignedAddress(&hostIpAddress);
|
||||||
|
|
||||||
WHBLogUdpInit();
|
WHBLogUdpInit();
|
||||||
|
|
||||||
//!*******************************************************************
|
//!*******************************************************************
|
||||||
//! Initialize FS *
|
//! Initialize FS *
|
||||||
@ -43,7 +42,7 @@ ON_APPLICATION_START() {
|
|||||||
|
|
||||||
DEBUG_FUNCTION_LINE("IOSUHAX_Open");
|
DEBUG_FUNCTION_LINE("IOSUHAX_Open");
|
||||||
int res = IOSUHAX_Open(nullptr);
|
int res = IOSUHAX_Open(nullptr);
|
||||||
if(res < 0) {
|
if (res < 0) {
|
||||||
DEBUG_FUNCTION_LINE("IOSUHAX_open failed");
|
DEBUG_FUNCTION_LINE("IOSUHAX_open failed");
|
||||||
VirtualMountDevice("fs:/");
|
VirtualMountDevice("fs:/");
|
||||||
} else {
|
} else {
|
||||||
@ -52,7 +51,7 @@ ON_APPLICATION_START() {
|
|||||||
|
|
||||||
DEBUG_FUNCTION_LINE("IOSUHAX_FSA_Open");
|
DEBUG_FUNCTION_LINE("IOSUHAX_FSA_Open");
|
||||||
fsaFd = IOSUHAX_FSA_Open();
|
fsaFd = IOSUHAX_FSA_Open();
|
||||||
if(fsaFd < 0) {
|
if (fsaFd < 0) {
|
||||||
DEBUG_FUNCTION_LINE("IOSUHAX_FSA_Open failed");
|
DEBUG_FUNCTION_LINE("IOSUHAX_FSA_Open failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,9 +62,9 @@ ON_APPLICATION_START() {
|
|||||||
mount_fs("storage_odd_updates", fsaFd, "/dev/odd02", "/vol/storage_odd_updates");
|
mount_fs("storage_odd_updates", fsaFd, "/dev/odd02", "/vol/storage_odd_updates");
|
||||||
mount_fs("storage_odd_content", fsaFd, "/dev/odd03", "/vol/storage_odd_content");
|
mount_fs("storage_odd_content", fsaFd, "/dev/odd03", "/vol/storage_odd_content");
|
||||||
mount_fs("storage_odd_content2", fsaFd, "/dev/odd04", "/vol/storage_odd_content2");
|
mount_fs("storage_odd_content2", fsaFd, "/dev/odd04", "/vol/storage_odd_content2");
|
||||||
mount_fs("storage_slc", fsaFd, NULL, "/vol/system");
|
mount_fs("storage_slc", fsaFd, nullptr, "/vol/system");
|
||||||
mount_fs("storage_mlc", fsaFd, NULL, "/vol/storage_mlc01");
|
mount_fs("storage_mlc", fsaFd, nullptr, "/vol/storage_mlc01");
|
||||||
mount_fs("storage_usb", fsaFd, NULL, "/vol/storage_usb01");
|
mount_fs("storage_usb", fsaFd, nullptr, "/vol/storage_usb01");
|
||||||
|
|
||||||
VirtualMountDevice("fs:/");
|
VirtualMountDevice("fs:/");
|
||||||
VirtualMountDevice("slccmpt01:/");
|
VirtualMountDevice("slccmpt01:/");
|
||||||
@ -87,15 +86,15 @@ ON_APPLICATION_START() {
|
|||||||
DCFlushRange(&thread, 4);
|
DCFlushRange(&thread, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void stopThread(){
|
void stopThread() {
|
||||||
BackgroundThread::destroyInstance();
|
BackgroundThread::destroyInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
ON_APPLICATION_REQUESTS_EXIT(){
|
ON_APPLICATION_REQUESTS_EXIT() {
|
||||||
DEBUG_FUNCTION_LINE("Ending ftp server");
|
DEBUG_FUNCTION_LINE("Ending ftp server");
|
||||||
stopThread();
|
stopThread();
|
||||||
|
|
||||||
if(iosuhaxMount) {
|
if (iosuhaxMount) {
|
||||||
IOSUHAX_sdio_disc_interface.shutdown();
|
IOSUHAX_sdio_disc_interface.shutdown();
|
||||||
IOSUHAX_usb_disc_interface.shutdown();
|
IOSUHAX_usb_disc_interface.shutdown();
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
|
|
||||||
|
51
src/net.c
51
src/net.c
@ -67,54 +67,54 @@ void initialise_network() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int32_t network_socket(uint32_t domain,uint32_t type,uint32_t protocol) {
|
int32_t network_socket(uint32_t domain, uint32_t type, uint32_t protocol) {
|
||||||
int sock = socket(domain, type, protocol);
|
int sock = socket(domain, type, protocol);
|
||||||
if(sock < 0) {
|
if (sock < 0) {
|
||||||
int err = -wiiu_geterrno();
|
int err = -wiiu_geterrno();
|
||||||
return (err < 0) ? err : sock;
|
return (err < 0) ? err : sock;
|
||||||
}
|
}
|
||||||
return sock;
|
return sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t network_bind(int32_t s,struct sockaddr *name,int32_t namelen) {
|
int32_t network_bind(int32_t s, struct sockaddr *name, int32_t namelen) {
|
||||||
int res = bind(s, name, namelen);
|
int res = bind(s, name, namelen);
|
||||||
if(res < 0) {
|
if (res < 0) {
|
||||||
int err = -wiiu_geterrno();
|
int err = -wiiu_geterrno();
|
||||||
return (err < 0) ? err : res;
|
return (err < 0) ? err : res;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t network_listen(int32_t s,uint32_t backlog) {
|
int32_t network_listen(int32_t s, uint32_t backlog) {
|
||||||
int res = listen(s, backlog);
|
int res = listen(s, backlog);
|
||||||
if(res < 0) {
|
if (res < 0) {
|
||||||
int err = -wiiu_geterrno();
|
int err = -wiiu_geterrno();
|
||||||
return (err < 0) ? err : res;
|
return (err < 0) ? err : res;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t network_accept(int32_t s,struct sockaddr *addr,int32_t *addrlen) {
|
int32_t network_accept(int32_t s, struct sockaddr *addr, int32_t *addrlen) {
|
||||||
int res = accept(s, addr, addrlen);
|
int res = accept(s, addr, addrlen);
|
||||||
if(res < 0) {
|
if (res < 0) {
|
||||||
int err = -wiiu_geterrno();
|
int err = -wiiu_geterrno();
|
||||||
return (err < 0) ? err : res;
|
return (err < 0) ? err : res;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t network_connect(int32_t s,struct sockaddr *addr, int32_t addrlen) {
|
int32_t network_connect(int32_t s, struct sockaddr *addr, int32_t addrlen) {
|
||||||
int res = connect(s, addr, addrlen);
|
int res = connect(s, addr, addrlen);
|
||||||
if(res < 0) {
|
if (res < 0) {
|
||||||
int err = -wiiu_geterrno();
|
int err = -wiiu_geterrno();
|
||||||
return (err < 0) ? err : res;
|
return (err < 0) ? err : res;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t network_read(int32_t s,void *mem,int32_t len) {
|
int32_t network_read(int32_t s, void *mem, int32_t len) {
|
||||||
int res = recv(s, mem, len, 0);
|
int res = recv(s, mem, len, 0);
|
||||||
if(res < 0) {
|
if (res < 0) {
|
||||||
int err = -wiiu_geterrno();
|
int err = -wiiu_geterrno();
|
||||||
return (err < 0) ? err : res;
|
return (err < 0) ? err : res;
|
||||||
}
|
}
|
||||||
@ -125,12 +125,12 @@ uint32_t network_gethostip() {
|
|||||||
return hostIpAddress;
|
return hostIpAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t network_write(int32_t s, const void *mem,int32_t len) {
|
int32_t network_write(int32_t s, const void *mem, int32_t len) {
|
||||||
int32_t transfered = 0;
|
int32_t transfered = 0;
|
||||||
|
|
||||||
while(len) {
|
while (len) {
|
||||||
int ret = send(s, mem, len, 0);
|
int ret = send(s, mem, len, 0);
|
||||||
if(ret < 0) {
|
if (ret < 0) {
|
||||||
int err = -wiiu_geterrno();
|
int err = -wiiu_geterrno();
|
||||||
transfered = (err < 0) ? err : ret;
|
transfered = (err < 0) ? err : ret;
|
||||||
break;
|
break;
|
||||||
@ -144,7 +144,7 @@ int32_t network_write(int32_t s, const void *mem,int32_t len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int32_t network_close(int32_t s) {
|
int32_t network_close(int32_t s) {
|
||||||
if(s < 0)
|
if (s < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return close(s);
|
return close(s);
|
||||||
@ -178,7 +178,7 @@ int32_t create_server(uint16_t port) {
|
|||||||
bindAddress.sin_addr.s_addr = htonl(INADDR_ANY);
|
bindAddress.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
|
|
||||||
int32_t ret;
|
int32_t ret;
|
||||||
if ((ret = network_bind(server, (struct sockaddr *)&bindAddress, sizeof(bindAddress))) < 0) {
|
if ((ret = network_bind(server, (struct sockaddr *) &bindAddress, sizeof(bindAddress))) < 0) {
|
||||||
network_close(server);
|
network_close(server);
|
||||||
//gxprintf("Error binding socket: [%i] %s\n", -ret, strerror(-ret));
|
//gxprintf("Error binding socket: [%i] %s\n", -ret, strerror(-ret));
|
||||||
return ret;
|
return ret;
|
||||||
@ -193,13 +193,14 @@ int32_t create_server(uint16_t port) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
typedef int32_t (*transferrer_type)(int32_t s, void *mem, int32_t len);
|
typedef int32_t (*transferrer_type)(int32_t s, void *mem, int32_t len);
|
||||||
|
|
||||||
static int32_t transfer_exact(int32_t s, char *buf, int32_t length, transferrer_type transferrer) {
|
static int32_t transfer_exact(int32_t s, char *buf, int32_t length, transferrer_type transferrer) {
|
||||||
int32_t result = 0;
|
int32_t result = 0;
|
||||||
int32_t remaining = length;
|
int32_t remaining = length;
|
||||||
int32_t bytes_transferred;
|
int32_t bytes_transferred;
|
||||||
set_blocking(s, true);
|
set_blocking(s, true);
|
||||||
while (remaining) {
|
while (remaining) {
|
||||||
try_again_with_smaller_buffer:
|
try_again_with_smaller_buffer:
|
||||||
bytes_transferred = transferrer(s, buf, MIN(remaining, (int) NET_BUFFER_SIZE));
|
bytes_transferred = transferrer(s, buf, MIN(remaining, (int) NET_BUFFER_SIZE));
|
||||||
if (bytes_transferred > 0) {
|
if (bytes_transferred > 0) {
|
||||||
remaining -= bytes_transferred;
|
remaining -= bytes_transferred;
|
||||||
@ -222,12 +223,12 @@ try_again_with_smaller_buffer:
|
|||||||
}
|
}
|
||||||
|
|
||||||
int32_t send_exact(int32_t s, char *buf, int32_t length) {
|
int32_t send_exact(int32_t s, char *buf, int32_t length) {
|
||||||
return transfer_exact(s, buf, length, (transferrer_type)network_write);
|
return transfer_exact(s, buf, length, (transferrer_type) network_write);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t send_from_file(int32_t s, FILE *f) {
|
int32_t send_from_file(int32_t s, FILE *f) {
|
||||||
char * buf = (char *) memalign(0x40, FREAD_BUFFER_SIZE);
|
char *buf = (char *) memalign(0x40, FREAD_BUFFER_SIZE);
|
||||||
if(!buf)
|
if (!buf)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
int32_t bytes_read;
|
int32_t bytes_read;
|
||||||
@ -245,19 +246,19 @@ int32_t send_from_file(int32_t s, FILE *f) {
|
|||||||
}
|
}
|
||||||
free(buf);
|
free(buf);
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
end:
|
end:
|
||||||
free(buf);
|
free(buf);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t recv_to_file(int32_t s, FILE *f) {
|
int32_t recv_to_file(int32_t s, FILE *f) {
|
||||||
char * buf = (char *) memalign(0x40, NET_BUFFER_SIZE);
|
char *buf = (char *) memalign(0x40, NET_BUFFER_SIZE);
|
||||||
if(!buf)
|
if (!buf)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
int32_t bytes_read;
|
int32_t bytes_read;
|
||||||
while (1) {
|
while (1) {
|
||||||
try_again_with_smaller_buffer:
|
try_again_with_smaller_buffer:
|
||||||
bytes_read = network_read(s, buf, NET_BUFFER_SIZE);
|
bytes_read = network_read(s, buf, NET_BUFFER_SIZE);
|
||||||
if (bytes_read < 0) {
|
if (bytes_read < 0) {
|
||||||
if (bytes_read == -EINVAL && NET_BUFFER_SIZE == MAX_NET_BUFFER_SIZE) {
|
if (bytes_read == -EINVAL && NET_BUFFER_SIZE == MAX_NET_BUFFER_SIZE) {
|
||||||
|
19
src/net.h
19
src/net.h
@ -43,13 +43,20 @@ extern "C"{
|
|||||||
void initialise_network();
|
void initialise_network();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int32_t network_socket(uint32_t domain,uint32_t type,uint32_t protocol);
|
int32_t network_socket(uint32_t domain, uint32_t type, uint32_t protocol);
|
||||||
int32_t network_bind(int32_t s,struct sockaddr *name,int32_t namelen);
|
|
||||||
int32_t network_listen(int32_t s,uint32_t backlog);
|
int32_t network_bind(int32_t s, struct sockaddr *name, int32_t namelen);
|
||||||
int32_t network_accept(int32_t s,struct sockaddr *addr,int32_t *addrlen);
|
|
||||||
int32_t network_connect(int32_t s,struct sockaddr *,int32_t);
|
int32_t network_listen(int32_t s, uint32_t backlog);
|
||||||
int32_t network_read(int32_t s,void *mem,int32_t len);
|
|
||||||
|
int32_t network_accept(int32_t s, struct sockaddr *addr, int32_t *addrlen);
|
||||||
|
|
||||||
|
int32_t network_connect(int32_t s, struct sockaddr *, int32_t);
|
||||||
|
|
||||||
|
int32_t network_read(int32_t s, void *mem, int32_t len);
|
||||||
|
|
||||||
int32_t network_close(int32_t s);
|
int32_t network_close(int32_t s);
|
||||||
|
|
||||||
uint32_t network_gethostip();
|
uint32_t network_gethostip();
|
||||||
|
|
||||||
int32_t set_blocking(int32_t s, bool blocking);
|
int32_t set_blocking(int32_t s, bool blocking);
|
||||||
|
@ -1,28 +1,22 @@
|
|||||||
#include "BackgroundThreadWrapper.hpp"
|
#include "BackgroundThreadWrapper.hpp"
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <coreinit/cache.h>
|
#include <coreinit/cache.h>
|
||||||
|
|
||||||
|
BackgroundThreadWrapper::BackgroundThreadWrapper(int32_t priority) : CThread(CThread::eAttributeAffCore2, priority, 0x100000) {
|
||||||
BackgroundThreadWrapper::BackgroundThreadWrapper(int32_t priority): CThread(CThread::eAttributeAffCore2, priority, 0x100000) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BackgroundThreadWrapper::~BackgroundThreadWrapper() {
|
BackgroundThreadWrapper::~BackgroundThreadWrapper() {
|
||||||
exitThread = 1;
|
exitThread = 1;
|
||||||
DCFlushRange((void*)&exitThread, 4);
|
DCFlushRange((void *) &exitThread, 4);
|
||||||
DEBUG_FUNCTION_LINE("Exit thread");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BackgroundThreadWrapper::executeThread() {
|
void BackgroundThreadWrapper::executeThread() {
|
||||||
while (true) {
|
while (true) {
|
||||||
if(exitThread) {
|
if (exitThread) {
|
||||||
DEBUG_FUNCTION_LINE("We want to exit");
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!whileLoop()){
|
if (!whileLoop()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DEBUG_FUNCTION_LINE("Exit!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,10 +4,12 @@
|
|||||||
#include <wut_types.h>
|
#include <wut_types.h>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
class BackgroundThreadWrapper: public CThread {
|
class BackgroundThreadWrapper : public CThread {
|
||||||
public:
|
public:
|
||||||
explicit BackgroundThreadWrapper(int32_t priority);
|
explicit BackgroundThreadWrapper(int32_t priority);
|
||||||
|
|
||||||
~BackgroundThreadWrapper() override;
|
~BackgroundThreadWrapper() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
[[nodiscard]] BOOL shouldExit() const {
|
[[nodiscard]] BOOL shouldExit() const {
|
||||||
return (exitThread == 1);
|
return (exitThread == 1);
|
||||||
@ -16,6 +18,7 @@ protected:
|
|||||||
void setThreadPriority(int32_t priority) override {
|
void setThreadPriority(int32_t priority) override {
|
||||||
CThread::setThreadPriority(priority);
|
CThread::setThreadPriority(priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::recursive_mutex mutex;
|
std::recursive_mutex mutex;
|
||||||
private:
|
private:
|
||||||
void executeThread() override;
|
void executeThread() override;
|
||||||
|
@ -25,23 +25,20 @@
|
|||||||
|
|
||||||
class CThread {
|
class CThread {
|
||||||
public:
|
public:
|
||||||
typedef void (* Callback)(CThread *thread, void *arg);
|
typedef void (*Callback)(CThread *thread, void *arg);
|
||||||
|
|
||||||
//! constructor
|
//! constructor
|
||||||
CThread(int32_t iAttr, int32_t iPriority = 16, int32_t iStackSize = 0x8000, CThread::Callback callback = NULL, void *callbackArg = NULL)
|
explicit CThread(int32_t iAttr, int32_t iPriority = 16, int32_t iStackSize = 0x8000, CThread::Callback callback = nullptr, void *callbackArg = nullptr)
|
||||||
: pThread(NULL)
|
: pThread(nullptr), pThreadStack(nullptr), pCallback(callback), pCallbackArg(callbackArg) {
|
||||||
, pThreadStack(NULL)
|
|
||||||
, pCallback(callback)
|
|
||||||
, pCallbackArg(callbackArg) {
|
|
||||||
//! save attribute assignment
|
//! save attribute assignment
|
||||||
iAttributes = iAttr;
|
iAttributes = iAttr;
|
||||||
//! allocate the thread
|
//! allocate the thread
|
||||||
pThread = (OSThread*)memalign(8, sizeof(OSThread));
|
pThread = (OSThread *) memalign(8, sizeof(OSThread));
|
||||||
//! allocate the stack
|
//! allocate the stack
|
||||||
pThreadStack = (uint8_t *) memalign(0x20, iStackSize);
|
pThreadStack = (uint8_t *) memalign(0x20, iStackSize);
|
||||||
//! create the thread
|
//! create the thread
|
||||||
if(pThread && pThreadStack)
|
if (pThread && pThreadStack)
|
||||||
OSCreateThread(pThread, &CThread::threadCallback, 1, (char*)this, pThreadStack+iStackSize, iStackSize, iPriority, iAttributes);
|
OSCreateThread(pThread, &CThread::threadCallback, 1, (char *) this, pThreadStack + iStackSize, iStackSize, iPriority, iAttributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! destructor
|
//! destructor
|
||||||
@ -51,72 +48,81 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static CThread *create(CThread::Callback callback, void *callbackArg, int32_t iAttr = eAttributeNone, int32_t iPriority = 16, int32_t iStackSize = 0x8000) {
|
static CThread *create(CThread::Callback callback, void *callbackArg, int32_t iAttr = eAttributeNone, int32_t iPriority = 16, int32_t iStackSize = 0x8000) {
|
||||||
return ( new CThread(iAttr, iPriority, iStackSize, callback, callbackArg) );
|
return (new CThread(iAttr, iPriority, iStackSize, callback, callbackArg));
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Get thread ID
|
//! Get thread ID
|
||||||
virtual void* getThread() const {
|
[[nodiscard]] virtual void *getThread() const {
|
||||||
return pThread;
|
return pThread;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Thread entry function
|
//! Thread entry function
|
||||||
virtual void executeThread(void) {
|
virtual void executeThread() {
|
||||||
if(pCallback)
|
if (pCallback)
|
||||||
pCallback(this, pCallbackArg);
|
pCallback(this, pCallbackArg);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Suspend thread
|
//! Suspend thread
|
||||||
virtual void suspendThread(void) {
|
virtual void suspendThread() {
|
||||||
if(isThreadSuspended()) return;
|
if (isThreadSuspended()) return;
|
||||||
if(pThread) OSSuspendThread(pThread);
|
if (pThread) OSSuspendThread(pThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Resume thread
|
//! Resume thread
|
||||||
virtual void resumeThread(void) {
|
virtual void resumeThread() {
|
||||||
if(!isThreadSuspended()) return;
|
if (!isThreadSuspended()) return;
|
||||||
if(pThread) OSResumeThread(pThread);
|
if (pThread) OSResumeThread(pThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Set thread priority
|
//! Set thread priority
|
||||||
virtual void setThreadPriority(int prio) {
|
virtual void setThreadPriority(int prio) {
|
||||||
if(pThread) OSSetThreadPriority(pThread, prio);
|
if (pThread) OSSetThreadPriority(pThread, prio);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Check if thread is suspended
|
//! Check if thread is suspended
|
||||||
virtual BOOL isThreadSuspended(void) const {
|
[[nodiscard]] virtual BOOL isThreadSuspended() const {
|
||||||
if(pThread) return OSIsThreadSuspended(pThread);
|
if (pThread) return OSIsThreadSuspended(pThread);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Check if thread is terminated
|
//! Check if thread is terminated
|
||||||
virtual BOOL isThreadTerminated(void) const {
|
[[nodiscard]] virtual BOOL isThreadTerminated() const {
|
||||||
if(pThread) return OSIsThreadTerminated(pThread);
|
if (pThread) return OSIsThreadTerminated(pThread);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Check if thread is running
|
//! Check if thread is running
|
||||||
virtual BOOL isThreadRunning(void) const {
|
[[nodiscard]] virtual BOOL isThreadRunning() const {
|
||||||
return !isThreadSuspended() && !isThreadRunning();
|
return !isThreadSuspended() && !isThreadRunning();
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Shutdown thread
|
//! Shutdown thread
|
||||||
virtual void shutdownThread(void) {
|
virtual void shutdownThread() {
|
||||||
//! wait for thread to finish
|
//! wait for thread to finish
|
||||||
if(pThread && !(iAttributes & eAttributeDetach)) {
|
if (pThread && !(iAttributes & eAttributeDetach)) {
|
||||||
if(isThreadSuspended())
|
if (isThreadSuspended())
|
||||||
resumeThread();
|
resumeThread();
|
||||||
|
|
||||||
OSJoinThread(pThread, NULL);
|
OSJoinThread(pThread, nullptr);
|
||||||
}
|
}
|
||||||
//! free the thread stack buffer
|
//! free the thread stack buffer
|
||||||
if(pThreadStack)
|
if (pThreadStack)
|
||||||
free(pThreadStack);
|
free(pThreadStack);
|
||||||
if(pThread)
|
if (pThread)
|
||||||
free(pThread);
|
free(pThread);
|
||||||
|
|
||||||
pThread = NULL;
|
pThread = nullptr;
|
||||||
pThreadStack = NULL;
|
pThreadStack = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Thread attributes
|
//! Thread attributes
|
||||||
enum eCThreadAttributes {
|
enum eCThreadAttributes {
|
||||||
eAttributeNone = 0x07,
|
eAttributeNone = 0x07,
|
||||||
eAttributeAffCore0 = 0x01,
|
eAttributeAffCore0 = 0x01,
|
||||||
eAttributeAffCore1 = 0x02,
|
eAttributeAffCore1 = 0x02,
|
||||||
eAttributeAffCore2 = 0x04,
|
eAttributeAffCore2 = 0x04,
|
||||||
eAttributeDetach = 0x08,
|
eAttributeDetach = 0x08,
|
||||||
eAttributePinnedAff = 0x10
|
eAttributePinnedAff = 0x10
|
||||||
};
|
};
|
||||||
private:
|
private:
|
||||||
static int threadCallback(int argc, const char **argv) {
|
static int threadCallback(int argc, const char **argv) {
|
||||||
@ -124,6 +130,7 @@ private:
|
|||||||
((CThread *) argv)->executeThread();
|
((CThread *) argv)->executeThread();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int iAttributes;
|
int iAttributes;
|
||||||
OSThread *pThread;
|
OSThread *pThread;
|
||||||
uint8_t *pThreadStack;
|
uint8_t *pThreadStack;
|
||||||
|
@ -16,7 +16,7 @@ extern "C" {
|
|||||||
|
|
||||||
#define DEBUG_FUNCTION_LINE(FMT, ARGS...)do { \
|
#define DEBUG_FUNCTION_LINE(FMT, ARGS...)do { \
|
||||||
WHBLogPrintf("[%23s]%30s@L%04d: " FMT "",__FILENAME__,__FUNCTION__, __LINE__, ## ARGS); \
|
WHBLogPrintf("[%23s]%30s@L%04d: " FMT "",__FILENAME__,__FUNCTION__, __LINE__, ## ARGS); \
|
||||||
} while (0);
|
} while (0)
|
||||||
|
|
||||||
#define DEBUG_FUNCTION_LINE_WRITE(FMT, ARGS...)do { \
|
#define DEBUG_FUNCTION_LINE_WRITE(FMT, ARGS...)do { \
|
||||||
WHBLogWritef("[%23s]%30s@L%04d: " FMT "",__FILENAME__,__FUNCTION__, __LINE__, ## ARGS); \
|
WHBLogWritef("[%23s]%30s@L%04d: " FMT "",__FILENAME__,__FUNCTION__, __LINE__, ## ARGS); \
|
||||||
|
@ -1,31 +1,31 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Copyright (C) 2008
|
* Copyright (C) 2008
|
||||||
* Joseph Jordan <joe.ftpii@psychlaw.com.au>
|
* Joseph Jordan <joe.ftpii@psychlaw.com.au>
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010
|
* Copyright (C) 2010
|
||||||
* by Dimok
|
* by Dimok
|
||||||
*
|
*
|
||||||
* This software is provided 'as-is', without any express or implied
|
* This software is provided 'as-is', without any express or implied
|
||||||
* warranty. In no event will the authors be held liable for any
|
* warranty. In no event will the authors be held liable for any
|
||||||
* damages arising from the use of this software.
|
* damages arising from the use of this software.
|
||||||
*
|
*
|
||||||
* Permission is granted to anyone to use this software for any
|
* Permission is granted to anyone to use this software for any
|
||||||
* purpose, including commercial applications, and to alter it and
|
* purpose, including commercial applications, and to alter it and
|
||||||
* redistribute it freely, subject to the following restrictions:
|
* redistribute it freely, subject to the following restrictions:
|
||||||
*
|
*
|
||||||
* 1. The origin of this software must not be misrepresented; you
|
* 1. The origin of this software must not be misrepresented; you
|
||||||
* must not claim that you wrote the original software. If you use
|
* must not claim that you wrote the original software. If you use
|
||||||
* this software in a product, an acknowledgment in the product
|
* this software in a product, an acknowledgment in the product
|
||||||
* documentation would be appreciated but is not required.
|
* documentation would be appreciated but is not required.
|
||||||
*
|
*
|
||||||
* 2. Altered source versions must be plainly marked as such, and
|
* 2. Altered source versions must be plainly marked as such, and
|
||||||
* must not be misrepresented as being the original software.
|
* must not be misrepresented as being the original software.
|
||||||
*
|
*
|
||||||
* 3. This notice may not be removed or altered from any source
|
* 3. This notice may not be removed or altered from any source
|
||||||
* distribution.
|
* distribution.
|
||||||
*
|
*
|
||||||
* for WiiXplorer 2010
|
* for WiiXplorer 2010
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "virtualpath.h"
|
#include "virtualpath.h"
|
||||||
@ -40,42 +40,37 @@ VIRTUAL_PARTITION *VIRTUAL_FS = NULL;
|
|||||||
uint8_t MAX_VIRTUAL_FS_VOL = 0;
|
uint8_t MAX_VIRTUAL_FS_VOL = 0;
|
||||||
VIRTUAL_PARTITION *VIRTUAL_FS_VOL = NULL;
|
VIRTUAL_PARTITION *VIRTUAL_FS_VOL = NULL;
|
||||||
|
|
||||||
void VirtualMountDevice(const char * path)
|
void VirtualMountDevice(const char *path) {
|
||||||
{
|
if (!path)
|
||||||
if(!path)
|
return;
|
||||||
return;
|
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
char name[255];
|
char name[255];
|
||||||
char alias[255];
|
char alias[255];
|
||||||
char prefix[255];
|
char prefix[255];
|
||||||
bool namestop = false;
|
bool namestop = false;
|
||||||
|
|
||||||
alias[0] = '/';
|
alias[0] = '/';
|
||||||
|
|
||||||
do
|
do {
|
||||||
{
|
if (path[i] == ':')
|
||||||
if(path[i] == ':')
|
namestop = true;
|
||||||
namestop = true;
|
|
||||||
|
|
||||||
if(!namestop)
|
if (!namestop) {
|
||||||
{
|
name[i] = path[i];
|
||||||
name[i] = path[i];
|
name[i + 1] = '\0';
|
||||||
name[i+1] = '\0';
|
alias[i + 1] = path[i];
|
||||||
alias[i+1] = path[i];
|
alias[i + 2] = '\0';
|
||||||
alias[i+2] = '\0';
|
}
|
||||||
}
|
|
||||||
|
|
||||||
prefix[i] = path[i];
|
prefix[i] = path[i];
|
||||||
prefix[i+1] = '\0';
|
prefix[i + 1] = '\0';
|
||||||
i++;
|
i++;
|
||||||
}
|
} while (path[i - 1] != '/');
|
||||||
while(path[i-1] != '/');
|
AddVirtualPath(name, alias, prefix);
|
||||||
AddVirtualPath(name, alias, prefix);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddVirtualPath(const char *name, const char *alias, const char *prefix)
|
void AddVirtualPath(const char *name, const char *alias, const char *prefix) {
|
||||||
{
|
|
||||||
if (!VIRTUAL_PARTITIONS) {
|
if (!VIRTUAL_PARTITIONS) {
|
||||||
VIRTUAL_PARTITIONS = (VIRTUAL_PARTITION *) malloc(sizeof(VIRTUAL_PARTITION));
|
VIRTUAL_PARTITIONS = (VIRTUAL_PARTITION *) malloc(sizeof(VIRTUAL_PARTITION));
|
||||||
}
|
}
|
||||||
@ -99,49 +94,48 @@ void AddVirtualPath(const char *name, const char *alias, const char *prefix)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void AddVirtualFSPath(const char *name, const char *alias, const char *prefix) {
|
void AddVirtualFSPath(const char *name, const char *alias, const char *prefix) {
|
||||||
if (!VIRTUAL_FS) {
|
if (!VIRTUAL_FS) {
|
||||||
VIRTUAL_FS = (VIRTUAL_PARTITION *) malloc(sizeof(VIRTUAL_PARTITION));
|
VIRTUAL_FS = (VIRTUAL_PARTITION *) malloc(sizeof(VIRTUAL_PARTITION));
|
||||||
}
|
}
|
||||||
|
|
||||||
VIRTUAL_PARTITION *tmp = realloc(VIRTUAL_FS, sizeof(VIRTUAL_PARTITION) * (MAX_VIRTUAL_FS + 1));
|
VIRTUAL_PARTITION *tmp = realloc(VIRTUAL_FS, sizeof(VIRTUAL_PARTITION) * (MAX_VIRTUAL_FS + 1));
|
||||||
if (!tmp) {
|
if (!tmp) {
|
||||||
if (VIRTUAL_FS) {
|
if (VIRTUAL_FS) {
|
||||||
free(VIRTUAL_FS);
|
free(VIRTUAL_FS);
|
||||||
VIRTUAL_FS = 0;
|
VIRTUAL_FS = 0;
|
||||||
}
|
}
|
||||||
MAX_VIRTUAL_FS = 0;
|
MAX_VIRTUAL_FS = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
VIRTUAL_FS = tmp;
|
VIRTUAL_FS = tmp;
|
||||||
|
|
||||||
VIRTUAL_FS[MAX_VIRTUAL_FS].name = strdup(name);
|
VIRTUAL_FS[MAX_VIRTUAL_FS].name = strdup(name);
|
||||||
|
|
||||||
MAX_VIRTUAL_FS++;
|
MAX_VIRTUAL_FS++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddVirtualFSVOLPath(const char *name, const char *alias, const char *prefix) {
|
void AddVirtualFSVOLPath(const char *name, const char *alias, const char *prefix) {
|
||||||
if (!VIRTUAL_FS_VOL) {
|
if (!VIRTUAL_FS_VOL) {
|
||||||
VIRTUAL_FS_VOL = (VIRTUAL_PARTITION *) malloc(sizeof(VIRTUAL_PARTITION));
|
VIRTUAL_FS_VOL = (VIRTUAL_PARTITION *) malloc(sizeof(VIRTUAL_PARTITION));
|
||||||
}
|
}
|
||||||
|
|
||||||
VIRTUAL_PARTITION *tmp = realloc(VIRTUAL_FS_VOL, sizeof(VIRTUAL_PARTITION) * (MAX_VIRTUAL_FS_VOL + 1));
|
VIRTUAL_PARTITION *tmp = realloc(VIRTUAL_FS_VOL, sizeof(VIRTUAL_PARTITION) * (MAX_VIRTUAL_FS_VOL + 1));
|
||||||
if (!tmp) {
|
if (!tmp) {
|
||||||
free(VIRTUAL_FS_VOL);
|
free(VIRTUAL_FS_VOL);
|
||||||
MAX_VIRTUAL_FS_VOL = 0;
|
MAX_VIRTUAL_FS_VOL = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
VIRTUAL_FS_VOL = tmp;
|
VIRTUAL_FS_VOL = tmp;
|
||||||
|
|
||||||
VIRTUAL_FS_VOL[MAX_VIRTUAL_FS_VOL].name = strdup(name);
|
VIRTUAL_FS_VOL[MAX_VIRTUAL_FS_VOL].name = strdup(name);
|
||||||
|
|
||||||
MAX_VIRTUAL_FS_VOL++;
|
MAX_VIRTUAL_FS_VOL++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MountVirtualDevices()
|
void MountVirtualDevices() {
|
||||||
{
|
|
||||||
VirtualMountDevice("fs:/");
|
VirtualMountDevice("fs:/");
|
||||||
VirtualMountDevice("slccmpt01:/");
|
VirtualMountDevice("slccmpt01:/");
|
||||||
VirtualMountDevice("storage_odd_tickets:/");
|
VirtualMountDevice("storage_odd_tickets:/");
|
||||||
@ -158,45 +152,45 @@ void MountVirtualDevices()
|
|||||||
AddVirtualFSVOLPath("content", NULL, NULL);
|
AddVirtualFSVOLPath("content", NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnmountVirtualPaths() {
|
void UnmountVirtualPaths() {
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
for (i = 0; i < MAX_VIRTUAL_PARTITIONS; i++) {
|
for (i = 0; i < MAX_VIRTUAL_PARTITIONS; i++) {
|
||||||
if (VIRTUAL_PARTITIONS[i].name) {
|
if (VIRTUAL_PARTITIONS[i].name) {
|
||||||
free(VIRTUAL_PARTITIONS[i].name);
|
free(VIRTUAL_PARTITIONS[i].name);
|
||||||
}
|
}
|
||||||
if (VIRTUAL_PARTITIONS[i].alias) {
|
if (VIRTUAL_PARTITIONS[i].alias) {
|
||||||
free(VIRTUAL_PARTITIONS[i].alias);
|
free(VIRTUAL_PARTITIONS[i].alias);
|
||||||
}
|
}
|
||||||
if (VIRTUAL_PARTITIONS[i].prefix) {
|
if (VIRTUAL_PARTITIONS[i].prefix) {
|
||||||
free(VIRTUAL_PARTITIONS[i].prefix);
|
free(VIRTUAL_PARTITIONS[i].prefix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < MAX_VIRTUAL_FS_VOL; i++) {
|
for (i = 0; i < MAX_VIRTUAL_FS_VOL; i++) {
|
||||||
if (VIRTUAL_FS_VOL[i].name) {
|
if (VIRTUAL_FS_VOL[i].name) {
|
||||||
free(VIRTUAL_FS_VOL[i].name);
|
free(VIRTUAL_FS_VOL[i].name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < MAX_VIRTUAL_FS; i++) {
|
for (i = 0; i < MAX_VIRTUAL_FS; i++) {
|
||||||
if (VIRTUAL_FS[i].name) {
|
if (VIRTUAL_FS[i].name) {
|
||||||
free(VIRTUAL_FS[i].name);
|
free(VIRTUAL_FS[i].name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (VIRTUAL_PARTITIONS) {
|
if (VIRTUAL_PARTITIONS) {
|
||||||
free(VIRTUAL_PARTITIONS);
|
free(VIRTUAL_PARTITIONS);
|
||||||
}
|
}
|
||||||
if (VIRTUAL_FS_VOL) {
|
if (VIRTUAL_FS_VOL) {
|
||||||
free(VIRTUAL_FS_VOL);
|
free(VIRTUAL_FS_VOL);
|
||||||
}
|
}
|
||||||
if (VIRTUAL_FS) {
|
if (VIRTUAL_FS) {
|
||||||
free(VIRTUAL_FS);
|
free(VIRTUAL_FS);
|
||||||
}
|
}
|
||||||
VIRTUAL_PARTITIONS = NULL;
|
VIRTUAL_PARTITIONS = NULL;
|
||||||
VIRTUAL_FS_VOL = NULL;
|
VIRTUAL_FS_VOL = NULL;
|
||||||
VIRTUAL_FS = NULL;
|
VIRTUAL_FS = NULL;
|
||||||
MAX_VIRTUAL_PARTITIONS = 0;
|
MAX_VIRTUAL_PARTITIONS = 0;
|
||||||
MAX_VIRTUAL_FS = 0;
|
MAX_VIRTUAL_FS = 0;
|
||||||
MAX_VIRTUAL_FS_VOL = 0;
|
MAX_VIRTUAL_FS_VOL = 0;
|
||||||
}
|
}
|
||||||
|
@ -1,32 +1,32 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Copyright (C) 2010
|
* Copyright (C) 2010
|
||||||
* by Dimok
|
* by Dimok
|
||||||
*
|
*
|
||||||
* Original VIRTUAL_PART Struct
|
* Original VIRTUAL_PART Struct
|
||||||
* Copyright (C) 2008
|
* Copyright (C) 2008
|
||||||
* Joseph Jordan <joe.ftpii@psychlaw.com.au>
|
* Joseph Jordan <joe.ftpii@psychlaw.com.au>
|
||||||
*
|
*
|
||||||
* This software is provided 'as-is', without any express or implied
|
* This software is provided 'as-is', without any express or implied
|
||||||
* warranty. In no event will the authors be held liable for any
|
* warranty. In no event will the authors be held liable for any
|
||||||
* damages arising from the use of this software.
|
* damages arising from the use of this software.
|
||||||
*
|
*
|
||||||
* Permission is granted to anyone to use this software for any
|
* Permission is granted to anyone to use this software for any
|
||||||
* purpose, including commercial applications, and to alter it and
|
* purpose, including commercial applications, and to alter it and
|
||||||
* redistribute it freely, subject to the following restrictions:
|
* redistribute it freely, subject to the following restrictions:
|
||||||
*
|
*
|
||||||
* 1. The origin of this software must not be misrepresented; you
|
* 1. The origin of this software must not be misrepresented; you
|
||||||
* must not claim that you wrote the original software. If you use
|
* must not claim that you wrote the original software. If you use
|
||||||
* this software in a product, an acknowledgment in the product
|
* this software in a product, an acknowledgment in the product
|
||||||
* documentation would be appreciated but is not required.
|
* documentation would be appreciated but is not required.
|
||||||
*
|
*
|
||||||
* 2. Altered source versions must be plainly marked as such, and
|
* 2. Altered source versions must be plainly marked as such, and
|
||||||
* must not be misrepresented as being the original software.
|
* must not be misrepresented as being the original software.
|
||||||
*
|
*
|
||||||
* 3. This notice may not be removed or altered from any source
|
* 3. This notice may not be removed or altered from any source
|
||||||
* distribution.
|
* distribution.
|
||||||
*
|
*
|
||||||
* for WiiXplorer 2010
|
* for WiiXplorer 2010
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
#ifndef _VIRTUALPATH_H_
|
#ifndef _VIRTUALPATH_H_
|
||||||
#define _VIRTUALPATH_H_
|
#define _VIRTUALPATH_H_
|
||||||
|
|
||||||
@ -38,26 +38,31 @@ extern "C"{
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char *name;
|
char *name;
|
||||||
char *alias;
|
char *alias;
|
||||||
char *prefix;
|
char *prefix;
|
||||||
bool inserted;
|
bool inserted;
|
||||||
} VIRTUAL_PARTITION;
|
} VIRTUAL_PARTITION;
|
||||||
|
|
||||||
extern VIRTUAL_PARTITION * VIRTUAL_PARTITIONS;
|
extern VIRTUAL_PARTITION *VIRTUAL_PARTITIONS;
|
||||||
extern uint8_t MAX_VIRTUAL_PARTITIONS;
|
extern uint8_t MAX_VIRTUAL_PARTITIONS;
|
||||||
|
|
||||||
extern VIRTUAL_PARTITION * VIRTUAL_FS;
|
extern VIRTUAL_PARTITION *VIRTUAL_FS;
|
||||||
extern uint8_t MAX_VIRTUAL_FS;
|
extern uint8_t MAX_VIRTUAL_FS;
|
||||||
|
|
||||||
extern VIRTUAL_PARTITION * VIRTUAL_FS_VOL;
|
extern VIRTUAL_PARTITION *VIRTUAL_FS_VOL;
|
||||||
extern uint8_t MAX_VIRTUAL_FS_VOL;
|
extern uint8_t MAX_VIRTUAL_FS_VOL;
|
||||||
|
|
||||||
void VirtualMountDevice(const char * devicepath);
|
void VirtualMountDevice(const char *devicepath);
|
||||||
|
|
||||||
void AddVirtualPath(const char *name, const char *alias, const char *prefix);
|
void AddVirtualPath(const char *name, const char *alias, const char *prefix);
|
||||||
|
|
||||||
void AddVirtualFSPath(const char *name, const char *alias, const char *prefix);
|
void AddVirtualFSPath(const char *name, const char *alias, const char *prefix);
|
||||||
|
|
||||||
void AddVirtualFSVOLPath(const char *name, const char *alias, const char *prefix);
|
void AddVirtualFSVOLPath(const char *name, const char *alias, const char *prefix);
|
||||||
|
|
||||||
void MountVirtualDevices();
|
void MountVirtualDevices();
|
||||||
|
|
||||||
void UnmountVirtualPaths();
|
void UnmountVirtualPaths();
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
363
src/vrt.c
363
src/vrt.c
@ -34,67 +34,67 @@ misrepresented as being the original software.
|
|||||||
#include "vrt.h"
|
#include "vrt.h"
|
||||||
|
|
||||||
static char *virtual_abspath(char *virtual_cwd, char *virtual_path) {
|
static char *virtual_abspath(char *virtual_cwd, char *virtual_path) {
|
||||||
char *path;
|
char *path;
|
||||||
if (virtual_path[0] == '/') {
|
if (virtual_path[0] == '/') {
|
||||||
path = virtual_path;
|
path = virtual_path;
|
||||||
} else {
|
} else {
|
||||||
size_t path_size = strlen(virtual_cwd) + strlen(virtual_path) + 1;
|
size_t path_size = strlen(virtual_cwd) + strlen(virtual_path) + 1;
|
||||||
if (path_size > MAXPATHLEN || !(path = malloc(path_size))) return NULL;
|
if (path_size > MAXPATHLEN || !(path = malloc(path_size))) return NULL;
|
||||||
strcpy(path, virtual_cwd);
|
strcpy(path, virtual_cwd);
|
||||||
strcat(path, virtual_path);
|
strcat(path, virtual_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *normalised_path = malloc(strlen(path) + 1);
|
char *normalised_path = malloc(strlen(path) + 1);
|
||||||
if (!normalised_path) goto end;
|
if (!normalised_path) goto end;
|
||||||
*normalised_path = '\0';
|
*normalised_path = '\0';
|
||||||
char *curr_dir = normalised_path;
|
char *curr_dir = normalised_path;
|
||||||
|
|
||||||
uint32_t state = 0; // 0:start, 1:slash, 2:dot, 3:dotdot
|
uint32_t state = 0; // 0:start, 1:slash, 2:dot, 3:dotdot
|
||||||
char *token = path;
|
char *token = path;
|
||||||
while (1) {
|
while (1) {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case 0:
|
case 0:
|
||||||
if (*token == '/') {
|
if (*token == '/') {
|
||||||
state = 1;
|
state = 1;
|
||||||
curr_dir = normalised_path + strlen(normalised_path);
|
curr_dir = normalised_path + strlen(normalised_path);
|
||||||
strncat(normalised_path, token, 1);
|
strncat(normalised_path, token, 1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if (*token == '.') state = 2;
|
if (*token == '.') state = 2;
|
||||||
else if (*token != '/') state = 0;
|
else if (*token != '/') state = 0;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
if (*token == '/' || !*token) {
|
if (*token == '/' || !*token) {
|
||||||
state = 1;
|
state = 1;
|
||||||
*(curr_dir + 1) = '\0';
|
*(curr_dir + 1) = '\0';
|
||||||
} else if (*token == '.') state = 3;
|
} else if (*token == '.') state = 3;
|
||||||
else state = 0;
|
else state = 0;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
if (*token == '/' || !*token) {
|
if (*token == '/' || !*token) {
|
||||||
state = 1;
|
state = 1;
|
||||||
*curr_dir = '\0';
|
*curr_dir = '\0';
|
||||||
char *prev_dir = strrchr(normalised_path, '/');
|
char *prev_dir = strrchr(normalised_path, '/');
|
||||||
if (prev_dir) curr_dir = prev_dir;
|
if (prev_dir) curr_dir = prev_dir;
|
||||||
else *curr_dir = '/';
|
else *curr_dir = '/';
|
||||||
*(curr_dir + 1) = '\0';
|
*(curr_dir + 1) = '\0';
|
||||||
} else state = 0;
|
} else state = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!*token) break;
|
if (!*token) break;
|
||||||
if (state == 0 || *token != '/') strncat(normalised_path, token, 1);
|
if (state == 0 || *token != '/') strncat(normalised_path, token, 1);
|
||||||
token++;
|
token++;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t end = strlen(normalised_path);
|
uint32_t end = strlen(normalised_path);
|
||||||
while (end > 1 && normalised_path[end - 1] == '/') {
|
while (end > 1 && normalised_path[end - 1] == '/') {
|
||||||
normalised_path[--end] = '\x00';
|
normalised_path[--end] = '\x00';
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
if (path != virtual_path) free(path);
|
if (path != virtual_path) free(path);
|
||||||
return normalised_path;
|
return normalised_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -106,52 +106,52 @@ static char *virtual_abspath(char *virtual_cwd, char *virtual_path) {
|
|||||||
Returns NULL to indicate that the client-visible path is invalid
|
Returns NULL to indicate that the client-visible path is invalid
|
||||||
*/
|
*/
|
||||||
char *to_real_path(char *virtual_cwd, char *virtual_path) {
|
char *to_real_path(char *virtual_cwd, char *virtual_path) {
|
||||||
errno = ENOENT;
|
errno = ENOENT;
|
||||||
if (strchr(virtual_path, ':')) {
|
if (strchr(virtual_path, ':')) {
|
||||||
return NULL; // colon is not allowed in virtual path, i've decided =P
|
return NULL; // colon is not allowed in virtual path, i've decided =P
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual_path = virtual_abspath(virtual_cwd, virtual_path);
|
virtual_path = virtual_abspath(virtual_cwd, virtual_path);
|
||||||
if (!virtual_path) return NULL;
|
if (!virtual_path) return NULL;
|
||||||
|
|
||||||
char *path = NULL;
|
char *path = NULL;
|
||||||
char *rest = virtual_path;
|
char *rest = virtual_path;
|
||||||
|
|
||||||
if (!strcmp("/", virtual_path)) {
|
if (!strcmp("/", virtual_path)) {
|
||||||
// indicate vfs-root with ""
|
// indicate vfs-root with ""
|
||||||
path = "";
|
path = "";
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *prefix = NULL;
|
const char *prefix = NULL;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
for (i = 0; i < MAX_VIRTUAL_PARTITIONS; i++) {
|
for (i = 0; i < MAX_VIRTUAL_PARTITIONS; i++) {
|
||||||
VIRTUAL_PARTITION *partition = VIRTUAL_PARTITIONS + i;
|
VIRTUAL_PARTITION *partition = VIRTUAL_PARTITIONS + i;
|
||||||
const char *alias = partition->alias;
|
const char *alias = partition->alias;
|
||||||
size_t alias_len = strlen(alias);
|
size_t alias_len = strlen(alias);
|
||||||
if (!strcasecmp(alias, virtual_path) || (!strncasecmp(alias, virtual_path, alias_len) && virtual_path[alias_len] == '/')) {
|
if (!strcasecmp(alias, virtual_path) || (!strncasecmp(alias, virtual_path, alias_len) && virtual_path[alias_len] == '/')) {
|
||||||
prefix = partition->prefix;
|
prefix = partition->prefix;
|
||||||
rest += alias_len;
|
rest += alias_len;
|
||||||
if (*rest == '/') rest++;
|
if (*rest == '/') rest++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!prefix) {
|
if (!prefix) {
|
||||||
errno = ENODEV;
|
errno = ENODEV;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t real_path_size = strlen(prefix) + strlen(rest) + 1;
|
size_t real_path_size = strlen(prefix) + strlen(rest) + 1;
|
||||||
if (real_path_size > MAXPATHLEN) goto end;
|
if (real_path_size > MAXPATHLEN) goto end;
|
||||||
|
|
||||||
path = malloc(real_path_size);
|
path = malloc(real_path_size);
|
||||||
if (!path) goto end;
|
if (!path) goto end;
|
||||||
strcpy(path, prefix);
|
strcpy(path, prefix);
|
||||||
strcat(path, rest);
|
strcat(path, rest);
|
||||||
|
|
||||||
end:
|
end:
|
||||||
free(virtual_path);
|
free(virtual_path);
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int checkdir(char *path) {
|
static int checkdir(char *path) {
|
||||||
@ -170,101 +170,105 @@ static int checkdir(char *path) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef void * (*path_func)(char *path, ...);
|
typedef void *(*path_func)(char *path, ...);
|
||||||
|
|
||||||
static void *with_virtual_path(void *virtual_cwd, void *void_f, char *virtual_path, int32_t failed, ...) {
|
static void *with_virtual_path(void *virtual_cwd, void *void_f, char *virtual_path, int32_t failed, ...) {
|
||||||
char *path = to_real_path(virtual_cwd, virtual_path);
|
char *path = to_real_path(virtual_cwd, virtual_path);
|
||||||
if (!path || !*path) return (void *)failed;
|
if (!path || !*path) return (void *) failed;
|
||||||
|
|
||||||
path_func f = (path_func)void_f;
|
path_func f = (path_func) void_f;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
void *args[3];
|
void *args[3];
|
||||||
unsigned int num_args = 0;
|
unsigned int num_args = 0;
|
||||||
va_start(ap, failed);
|
va_start(ap, failed);
|
||||||
do {
|
do {
|
||||||
void *arg = va_arg(ap, void *);
|
void *arg = va_arg(ap, void *);
|
||||||
if (!arg) break;
|
if (!arg) break;
|
||||||
args[num_args++] = arg;
|
args[num_args++] = arg;
|
||||||
} while (1);
|
} while (1);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
void *result;
|
void *result;
|
||||||
switch (num_args) {
|
switch (num_args) {
|
||||||
case 0: result = f(path); break;
|
case 0:
|
||||||
case 1: result = f(path, args[0]); break;
|
result = f(path);
|
||||||
case 2: result = f(path, args[0], args[1]); break;
|
break;
|
||||||
case 3: result = f(path, args[0], args[1], args[2]); break;
|
case 1:
|
||||||
default: result = (void *)failed; break;
|
result = f(path, args[0]);
|
||||||
}
|
break;
|
||||||
|
case 2:
|
||||||
|
result = f(path, args[0], args[1]);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
result = f(path, args[0], args[1], args[2]);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
result = (void *) failed;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
free(path);
|
free(path);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE *vrt_fopen(char *cwd, char *path, char *mode) {
|
FILE *vrt_fopen(char *cwd, char *path, char *mode) {
|
||||||
return with_virtual_path(cwd, fopen, path, 0, mode, NULL);
|
return with_virtual_path(cwd, fopen, path, 0, mode, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int vrt_stat(char *cwd, char *path, struct stat *st) {
|
int vrt_stat(char *cwd, char *path, struct stat *st) {
|
||||||
char *real_path = to_real_path(cwd, path);
|
char *real_path = to_real_path(cwd, path);
|
||||||
if (!real_path)
|
if (!real_path) {
|
||||||
{
|
|
||||||
return -1;
|
return -1;
|
||||||
|
} else if (!*real_path || (strcmp(path, ".") == 0) || (strlen(cwd) == 1) || ((strlen(cwd) > 1) && (strcmp(path, "..") == 0))) {
|
||||||
|
st->st_mode = S_IFDIR;
|
||||||
|
st->st_size = 31337;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
else if (!*real_path || (strcmp(path, ".") == 0) || (strlen(cwd) == 1) || ((strlen(cwd) > 1) && (strcmp(path, "..") == 0)))
|
free(real_path);
|
||||||
{
|
return (int) with_virtual_path(cwd, stat, path, -1, st, NULL);
|
||||||
st->st_mode = S_IFDIR;
|
|
||||||
st->st_size = 31337;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
free(real_path);
|
|
||||||
return (int)with_virtual_path(cwd, stat, path, -1, st, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vrt_checkdir(char *cwd, char *path) {
|
static int vrt_checkdir(char *cwd, char *path) {
|
||||||
char *real_path = to_real_path(cwd, path);
|
char *real_path = to_real_path(cwd, path);
|
||||||
if (!real_path)
|
if (!real_path) {
|
||||||
{
|
return -1;
|
||||||
return -1;
|
} else if (!*real_path || (strcmp(path, ".") == 0) || (strlen(cwd) == 1) || ((strlen(cwd) > 1) && (strcmp(path, "..") == 0))) {
|
||||||
}
|
return 0;
|
||||||
else if (!*real_path || (strcmp(path, ".") == 0) || (strlen(cwd) == 1) || ((strlen(cwd) > 1) && (strcmp(path, "..") == 0)))
|
}
|
||||||
{
|
free(real_path);
|
||||||
return 0;
|
return (int) with_virtual_path(cwd, checkdir, path, -1, NULL);
|
||||||
}
|
|
||||||
free(real_path);
|
|
||||||
return (int)with_virtual_path(cwd, checkdir, path, -1, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int vrt_chdir(char *cwd, char *path) {
|
int vrt_chdir(char *cwd, char *path) {
|
||||||
|
|
||||||
if (vrt_checkdir(cwd, path)) {
|
if (vrt_checkdir(cwd, path)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
char *abspath = virtual_abspath(cwd, path);
|
char *abspath = virtual_abspath(cwd, path);
|
||||||
if (!abspath) {
|
if (!abspath) {
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
strcpy(cwd, abspath);
|
strcpy(cwd, abspath);
|
||||||
if (cwd[1]) strcat(cwd, "/");
|
if (cwd[1]) strcat(cwd, "/");
|
||||||
free(abspath);
|
free(abspath);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int vrt_unlink(char *cwd, char *path) {
|
int vrt_unlink(char *cwd, char *path) {
|
||||||
return (int)with_virtual_path(cwd, unlink, path, -1, NULL);
|
return (int) with_virtual_path(cwd, unlink, path, -1, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int vrt_mkdir(char *cwd, char *path, mode_t mode) {
|
int vrt_mkdir(char *cwd, char *path, mode_t mode) {
|
||||||
return (int)with_virtual_path(cwd, mkdir, path, -1, mode, NULL);
|
return (int) with_virtual_path(cwd, mkdir, path, -1, mode, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int vrt_rename(char *cwd, char *from_path, char *to_path) {
|
int vrt_rename(char *cwd, char *from_path, char *to_path) {
|
||||||
char *real_to_path = to_real_path(cwd, to_path);
|
char *real_to_path = to_real_path(cwd, to_path);
|
||||||
if (!real_to_path || !*real_to_path) return -1;
|
if (!real_to_path || !*real_to_path) return -1;
|
||||||
int result = (int)with_virtual_path(cwd, rename, from_path, -1, real_to_path, NULL);
|
int result = (int) with_virtual_path(cwd, rename, from_path, -1, real_to_path, NULL);
|
||||||
free(real_to_path);
|
free(real_to_path);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -328,11 +332,11 @@ struct dirent *vrt_readdir(DIR_P *pDir) {
|
|||||||
DIR *iter = pDir->dir;
|
DIR *iter = pDir->dir;
|
||||||
if (pDir->virt_root || pDir->virtual_fs || pDir->virtual_fs_vol) {
|
if (pDir->virt_root || pDir->virtual_fs || pDir->virtual_fs_vol) {
|
||||||
int max = MAX_VIRTUAL_PARTITIONS;
|
int max = MAX_VIRTUAL_PARTITIONS;
|
||||||
VIRTUAL_PARTITION * PARTITION_PTR = VIRTUAL_PARTITIONS;
|
VIRTUAL_PARTITION *PARTITION_PTR = VIRTUAL_PARTITIONS;
|
||||||
if(pDir->virtual_fs){
|
if (pDir->virtual_fs) {
|
||||||
max = MAX_VIRTUAL_FS;
|
max = MAX_VIRTUAL_FS;
|
||||||
PARTITION_PTR = VIRTUAL_FS;
|
PARTITION_PTR = VIRTUAL_FS;
|
||||||
} else if (pDir->virtual_fs_vol){
|
} else if (pDir->virtual_fs_vol) {
|
||||||
max = MAX_VIRTUAL_FS_VOL;
|
max = MAX_VIRTUAL_FS_VOL;
|
||||||
PARTITION_PTR = VIRTUAL_FS_VOL;
|
PARTITION_PTR = VIRTUAL_FS_VOL;
|
||||||
}
|
}
|
||||||
@ -340,9 +344,9 @@ struct dirent *vrt_readdir(DIR_P *pDir) {
|
|||||||
VIRTUAL_PARTITION *partition = PARTITION_PTR + (int) iter->position;
|
VIRTUAL_PARTITION *partition = PARTITION_PTR + (int) iter->position;
|
||||||
if (partition->inserted) {
|
if (partition->inserted) {
|
||||||
iter->fileData.d_type = DT_DIR;
|
iter->fileData.d_type = DT_DIR;
|
||||||
if(pDir->virtual_fs || pDir->virtual_fs_vol){
|
if (pDir->virtual_fs || pDir->virtual_fs_vol) {
|
||||||
strcpy(iter->fileData.d_name, partition->name);
|
strcpy(iter->fileData.d_name, partition->name);
|
||||||
}else{
|
} else {
|
||||||
strcpy(iter->fileData.d_name, partition->alias + 1);
|
strcpy(iter->fileData.d_name, partition->alias + 1);
|
||||||
}
|
}
|
||||||
iter->position++;
|
iter->position++;
|
||||||
@ -356,21 +360,20 @@ struct dirent *vrt_readdir(DIR_P *pDir) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int vrt_closedir(DIR_P *iter) {
|
int vrt_closedir(DIR_P *iter) {
|
||||||
if(!iter) return -1;
|
if (!iter) return -1;
|
||||||
|
|
||||||
if(iter->dir)
|
if (iter->dir) {
|
||||||
{
|
if (iter->virt_root)
|
||||||
if (iter->virt_root)
|
free(iter->dir);
|
||||||
free(iter->dir);
|
else
|
||||||
else
|
closedir(iter->dir);
|
||||||
closedir(iter->dir);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// root path is not allocated
|
// root path is not allocated
|
||||||
if(iter->path && *iter->path != 0)
|
if (iter->path && *iter->path != 0)
|
||||||
free(iter->path);
|
free(iter->path);
|
||||||
|
|
||||||
free(iter);
|
free(iter);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
21
src/vrt.h
21
src/vrt.h
@ -32,25 +32,32 @@ extern "C"{
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/dirent.h>
|
#include <sys/dirent.h>
|
||||||
|
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
DIR *dir;
|
||||||
DIR *dir;
|
char *path;
|
||||||
char *path;
|
uint8_t virt_root;
|
||||||
uint8_t virt_root;
|
uint8_t virtual_fs;
|
||||||
uint8_t virtual_fs;
|
uint8_t virtual_fs_vol;
|
||||||
uint8_t virtual_fs_vol;
|
|
||||||
} DIR_P;
|
} DIR_P;
|
||||||
|
|
||||||
char *to_real_path(char *virtual_cwd, char *virtual_path);
|
char *to_real_path(char *virtual_cwd, char *virtual_path);
|
||||||
|
|
||||||
FILE *vrt_fopen(char *cwd, char *path, char *mode);
|
FILE *vrt_fopen(char *cwd, char *path, char *mode);
|
||||||
|
|
||||||
int vrt_stat(char *cwd, char *path, struct stat *st);
|
int vrt_stat(char *cwd, char *path, struct stat *st);
|
||||||
|
|
||||||
int vrt_chdir(char *cwd, char *path);
|
int vrt_chdir(char *cwd, char *path);
|
||||||
|
|
||||||
int vrt_unlink(char *cwd, char *path);
|
int vrt_unlink(char *cwd, char *path);
|
||||||
|
|
||||||
int vrt_mkdir(char *cwd, char *path, mode_t mode);
|
int vrt_mkdir(char *cwd, char *path, mode_t mode);
|
||||||
|
|
||||||
int vrt_rename(char *cwd, char *from_path, char *to_path);
|
int vrt_rename(char *cwd, char *from_path, char *to_path);
|
||||||
|
|
||||||
DIR_P *vrt_opendir(char *cwd, char *path);
|
DIR_P *vrt_opendir(char *cwd, char *path);
|
||||||
|
|
||||||
struct dirent *vrt_readdir(DIR_P *iter);
|
struct dirent *vrt_readdir(DIR_P *iter);
|
||||||
|
|
||||||
int vrt_closedir(DIR_P *iter);
|
int vrt_closedir(DIR_P *iter);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
Loading…
Reference in New Issue
Block a user