Skip to content

Commit 36a0600

Browse files
committed
fix many nx bugs.
1. i made multiple changes to utils.c and vfs_nx.c without testing before making a release, all because i thought doing so at 2am would be a great idea. 2. i then decided, 10 minutes before leaving for work, to try and fix a reported bug and make a new release and label it "fixed" lol. actual fixes: - [NX] check that the src/dst fs is the same before attempting a rename. - [NX] correctly translate device path to fs path. - fix path building when listing a directory if cwd is root '/'. - [NX] block sleep mode when using application build. - [NX] fail on cross fs rename.
1 parent c412ad9 commit 36a0600

File tree

13 files changed

+111
-65
lines changed

13 files changed

+111
-65
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.13)
22

33
project(ftpsrv
44
LANGUAGES C
5-
VERSION 0.1.1
5+
VERSION 0.1.2
66
DESCRIPTION "small and fast ftp server"
77
)
88

src/ftpsrv.c

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,8 @@ static int build_fullpath(const struct FtpSession* session, struct Pathname* out
293293
}
294294

295295
// return an error if the output was truncated or it failed.
296-
if (rc < 0 || rc > sizeof(*out)) {
296+
if (rc < 0 || rc >= sizeof(*out)) {
297+
errno = ENAMETOOLONG;
297298
rc = -1;
298299
} else {
299300
rc = 0;
@@ -323,7 +324,6 @@ static inline struct Pathname fix_path_for_device(const struct Pathname* path) {
323324
static int ftp_build_list_entry(struct FtpSession* session, const time_t cur_time, const struct Pathname* fullpath, const char* name, const struct stat* st, int nlist) {
324325
int rc;
325326
struct FtpTransfer* transfer = &session->transfer;
326-
// char buf[1024 * 4] = {0};
327327

328328
if (nlist) {
329329
rc = snprintf(transfer->list_buf, sizeof(transfer->list_buf), "%s" TELNET_EOL, name);
@@ -393,6 +393,7 @@ static int ftp_build_list_entry(struct FtpSession* session, const time_t cur_tim
393393

394394
if (rc <= 0 || rc > sizeof(transfer->list_buf)) {
395395
// don't send anything on error or truncated
396+
errno = ENAMETOOLONG;
396397
rc = -1;
397398
} else {
398399
transfer->size = rc;
@@ -490,6 +491,7 @@ static void ftp_dir_data_transfer_progress(struct FtpSession* session) {
490491
const time_t cur_time = time(NULL);
491492
const bool nlist = session->transfer.mode == FTP_TRANSFER_MODE_NLST;
492493
const bool device_list = g_ftp.cfg.devices && g_ftp.cfg.devices_count && !strcmp("/", session->temp_path.s);
494+
const bool is_root = !strcmp("/", session->temp_path.s);
493495
struct FtpTransfer* transfer = &session->transfer;
494496

495497
// send as much data as possible.
@@ -543,8 +545,14 @@ static void ftp_dir_data_transfer_progress(struct FtpSession* session) {
543545
continue;
544546
}
545547

546-
static struct Pathname filepath;
547-
int rc = snprintf(filepath.s, sizeof(filepath), "%s/%s", session->temp_path.s, name);
548+
int rc;
549+
struct Pathname filepath;
550+
if (is_root) {
551+
rc = snprintf(filepath.s, sizeof(filepath), "%s%s", session->temp_path.s, name);
552+
} else {
553+
rc = snprintf(filepath.s, sizeof(filepath), "%s/%s", session->temp_path.s, name);
554+
}
555+
548556
if (rc <= 0 || rc > sizeof(filepath)) {
549557
continue;
550558
}
@@ -1115,7 +1123,7 @@ static void ftp_list_directory(struct FtpSession* session, const char* data, int
11151123
struct stat st = {0};
11161124
rc = ftp_vfs_lstat(session->temp_path.s, &st);
11171125
if (rc < 0) {
1118-
ftp_client_msg(session, "450 Requested file action not taken. %s %s", strerror(errno), session->temp_path.s);
1126+
ftp_client_msg(session, "450 Requested file action not taken. %s", strerror(errno));
11191127
} else {
11201128
if (S_ISDIR(st.st_mode)) {
11211129
rc = ftp_vfs_opendir(&session->transfer.dir_vfs, session->temp_path.s);
@@ -1124,7 +1132,7 @@ static void ftp_list_directory(struct FtpSession* session, const char* data, int
11241132
} else {
11251133
rc = ftp_data_open(session);
11261134
if (rc < 0) {
1127-
ftp_client_msg(session, "425 Can't open data connection. %s rc: %d", strerror(errno), errno);
1135+
ftp_client_msg(session, "425 Can't open data connection. %s", strerror(errno));
11281136
} else {
11291137
session->transfer.mode = mode;
11301138
return;
@@ -1180,7 +1188,7 @@ static void ftp_cmd_STAT(struct FtpSession* session, const char* data) {
11801188

11811189
// HELP <CRLF> | 211, 214, 500, 501, 502, 421
11821190
static void ftp_cmd_HELP(struct FtpSession* session, const char* data) {
1183-
ftp_client_msg(session, "214 ftpsrv 0.1.1 By TotalJustice.");
1191+
ftp_client_msg(session, "214 ftpsrv 0.1.2 By TotalJustice.");
11841192
}
11851193

11861194
// NOOP <CRLF> | 200, 500, 421

src/platform/3ds/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ int main(void) {
126126
gfxInitDefault();
127127
consoleInit(GFX_TOP, &topScreen);
128128
consoleInit(GFX_BOTTOM, &bottomScreen);
129-
consolePrint("\n[ftpsrv 0.1.1 By TotalJustice]\n\n");
129+
consolePrint("\n[ftpsrv 0.1.2 By TotalJustice]\n\n");
130130

131131
g_ftpsrv_config.log_callback = ftp_log_callback;
132132
g_ftpsrv_config.anon = ini_getl("Login", "anon", 0, INI_PATH);

src/platform/nds/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ int main(void) {
101101
consoleInit(&topScreen, 3,BgType_Text4bpp, BgSize_T_256x256, 31, 0, true, true);
102102
consoleInit(&bottomScreen, 3,BgType_Text4bpp, BgSize_T_256x256, 31, 0, false, true);
103103

104-
consolePrint("\n[ftpsrv 0.1.1 By TotalJustice]\n\n");
104+
consolePrint("\n[ftpsrv 0.1.2 By TotalJustice]\n\n");
105105

106106
// init sd card.
107107
if (!fatInitDefault()) {

src/platform/nx/main.c

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@
1515
#include <switch.h>
1616
#include <minIni.h>
1717

18-
#define TEXT_NORMAL "\033[0m"
19-
#define TEXT_RED "\033[0;31m"
20-
#define TEXT_GREEN "\033[0;32m"
21-
#define TEXT_YELLOW "\033[0;33m"
22-
#define TEXT_BLUE "\033[0;34m"
18+
#define TEXT_NORMAL "\033[37;1m"
19+
#define TEXT_RED "\033[31;1m"
20+
#define TEXT_GREEN "\033[32;1m"
21+
#define TEXT_YELLOW "\033[33;1m"
22+
#define TEXT_BLUE "\033[34;1m"
2323

2424
struct CallbackData {
2525
enum FTP_API_LOG_TYPE type;
@@ -28,7 +28,7 @@ struct CallbackData {
2828

2929
static const char INI_PATH[FS_MAX_PATH] = {"/config/ftpsrv/config.ini"};
3030
static struct FtpSrvConfig g_ftpsrv_config = {0};
31-
static struct FtpSrvDevice g_devices[32] = {0};
31+
static struct FtpSrvDevice g_devices[FsDevWrap_DEVICES_MAX] = {0};
3232
static int g_devices_count;
3333

3434
static PadState g_pad;
@@ -43,7 +43,7 @@ static bool IsApplication(void) {
4343
}
4444

4545
static void add_device(const char* path) {
46-
if (g_devices_count < 32) {
46+
if (g_devices_count < FsDevWrap_DEVICES_MAX) {
4747
sprintf(g_devices[g_devices_count++].mount, "%s:", path);
4848
}
4949
}
@@ -121,7 +121,7 @@ static int error_loop(const char* msg) {
121121
}
122122

123123
int main(int argc, char** argv) {
124-
consolePrint("\n[ftpsrv 0.1.1 By TotalJustice]\n\n");
124+
consolePrint("\n[ftpsrv 0.1.2 By TotalJustice]\n\n");
125125

126126
padConfigureInput(8, HidNpadStyleSet_NpadStandard);
127127
padInitializeDefault(&g_pad);
@@ -199,6 +199,7 @@ int main(int argc, char** argv) {
199199
printf(TEXT_YELLOW "user: %s" TEXT_NORMAL "\n", g_ftpsrv_config.user);
200200
printf(TEXT_YELLOW "pass: %s" TEXT_NORMAL "\n", g_ftpsrv_config.pass);
201201
}
202+
printf(TEXT_YELLOW "mount_devices: %d" TEXT_NORMAL "\n", mount_devices);
202203
printf(TEXT_YELLOW "\nconfig: %s" TEXT_NORMAL "\n", INI_PATH);
203204
printf("\n");
204205
consoleUpdate(NULL);
@@ -318,16 +319,18 @@ void userAppInit(void) {
318319
if (R_FAILED(rc = fsdev_wrapMountSdmc()))
319320
diagAbortWithResult(rc);
320321

322+
appletRequestToAcquireSleepLock();
321323
add_device("sdmc");
322324
consoleInit(NULL);
323325
}
324326

325327
void userAppExit(void) {
328+
consoleExit(NULL);
326329
accountExit();
327330
socketExit();
328331
bsdExit();
329332
nifmExit();
330-
consoleExit(NULL);
331333
fsdev_wrapUnmountAll();
334+
appletReleaseSleepLock();
332335
appletUnlockExit();
333336
}

src/platform/nx/main_sysmod.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@
88

99
static const char* INI_PATH = "/config/ftpsrv/config.ini";
1010
static struct FtpSrvConfig g_ftpsrv_config = {0};
11-
static struct FtpSrvDevice g_devices[32] = {0};
11+
static struct FtpSrvDevice g_devices[FsDevWrap_DEVICES_MAX] = {0};
1212
static int g_devices_count = 0;
1313

1414
static void add_device(const char* path) {
15-
if (g_devices_count < 32) {
15+
if (g_devices_count < FsDevWrap_DEVICES_MAX) {
1616
sprintf(g_devices[g_devices_count++].mount, "%s:", path);
1717
}
1818
}

src/platform/nx/sysftp.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "sys-ftp",
3-
"version": "0.1.1",
3+
"version": "0.1.2",
44
"program_id": "0x420000000000011B",
55
"program_id_range_min": "0x420000000000011B",
66
"program_id_range_max": "0x420000000000011B",

src/platform/nx/utils.c

Lines changed: 64 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
#include "utils.h"
22
#include <string.h>
33
#include <stdio.h>
4-
5-
#define FsDevWrap_DEVICES_MAX 32
4+
#include <errno.h>
65

76
#define FsDevWrap_Module 0x505
87

@@ -12,14 +11,25 @@ enum FsDevWrap_Error {
1211

1312
struct FsDevWrapEntry {
1413
FsFileSystem fs;
15-
char path[32];
14+
char path[FsDevWrap_PATH_MAX];
1615
const char* shortcut;
1716
bool active;
1817
bool own;
1918
};
2019

2120
static struct FsDevWrapEntry g_fsdev_entries[FsDevWrap_DEVICES_MAX] = {0};
2221

22+
static struct FsDevWrapEntry* find_entry(const char* path) {
23+
for (int i = 0; i < FsDevWrap_DEVICES_MAX; i++) {
24+
const size_t dev_len = strlen(g_fsdev_entries[i].path);
25+
if (g_fsdev_entries[i].active && !strncmp(g_fsdev_entries[i].path, path, dev_len) && (path[dev_len] == '\0' || path[dev_len] == ':')) {
26+
return &g_fsdev_entries[i];
27+
}
28+
}
29+
30+
return NULL;
31+
}
32+
2333
static Result mount_helper(const char* path, FsFileSystem fs) {
2434
if (fsdev_wrapMountDevice(path, NULL, fs, true)) {
2535
fsFsClose(&fs);
@@ -83,65 +93,80 @@ Result fsdev_wrapMountSaveBcat(const char* path, u64 id) {
8393
}
8494

8595
FsFileSystem* fsdev_wrapGetDeviceFileSystem(const char* name) {
86-
size_t len = strlen(name);
87-
if (!len) {
96+
struct FsDevWrapEntry* entry = find_entry(name);
97+
if (!entry) {
98+
errno = ENODEV;
8899
return NULL;
89100
}
90-
91-
const char* sdmc_path = "sdmc";
92-
if (name[0] == '/') {
93-
name = sdmc_path;
94-
}
95-
96-
for (int i = 0; i < FsDevWrap_DEVICES_MAX; i++) {
97-
if (g_fsdev_entries[i].active && !strncmp(name, g_fsdev_entries[i].path, strlen(name))) {
98-
return &g_fsdev_entries[i].fs;
99-
}
100-
}
101-
return NULL;
101+
return &entry->fs;
102102
}
103103

104104
int fsdev_wrapTranslatePath(const char *path, FsFileSystem** device, char *outpath) {
105-
size_t len = strlen(path);
106-
if (!len) {
105+
int rc = 0;
106+
char nxpath[FS_MAX_PATH];
107+
108+
if (!path) {
109+
errno = ENODEV;
107110
return -1;
108111
}
109112

110-
const char* sdmc_path = "sdmc:/";
111113
if (path[0] == '/') {
112-
path = sdmc_path;
114+
if (strchr(path, ':')) {
115+
strcpy(nxpath, path + 1);
116+
} else {
117+
rc = snprintf(nxpath, sizeof(nxpath), "%s%s", "sdmc:", path);
118+
if (rc <= 0 || rc >= sizeof(nxpath)) {
119+
errno = ENAMETOOLONG;
120+
return -1;
121+
}
122+
}
123+
} else {
124+
strcpy(nxpath, path);
113125
}
114126

115-
const char* colon = memchr(path, ':', len);
116-
if (!colon || colon == path) {
127+
const char* colon = strchr(nxpath, ':');
128+
if (!colon) {
129+
errno = ENODEV;
117130
return -1;
118131
}
119132

120-
const size_t device_name_len = colon - path;
133+
struct FsDevWrapEntry* entry = find_entry(nxpath);
134+
if (!entry) {
135+
errno = ENODEV;
136+
return -1;
137+
}
121138

122-
for (int i = 0; i < FsDevWrap_DEVICES_MAX; i++) {
123-
if (g_fsdev_entries[i].active && !strncmp(path, g_fsdev_entries[i].path, device_name_len)) {
124-
if (device) {
125-
*device = &g_fsdev_entries[i].fs;
126-
}
127-
if (g_fsdev_entries[i].shortcut) {
128-
sprintf(outpath, "/%s/%s", g_fsdev_entries[i].shortcut, colon + 1);
129-
} else {
130-
strcpy(outpath, colon + 1);
131-
}
139+
if (device) {
140+
*device = &entry->fs;
141+
}
132142

133-
if (outpath[0] == '\0') {
134-
outpath[0] = '/';
135-
outpath[1] = '\0';
143+
if (outpath) {
144+
if (entry->shortcut) {
145+
rc = snprintf(outpath, FS_MAX_PATH, "/%s/%s", entry->shortcut, colon + 1);
146+
if (rc <= 0 || rc >= FS_MAX_PATH) {
147+
errno = ENAMETOOLONG;
148+
return -1;
136149
}
137-
return 0;
150+
} else {
151+
strcpy(outpath, colon + 1);
152+
}
153+
154+
if (outpath[0] == '\0') {
155+
outpath[0] = '/';
156+
outpath[1] = '\0';
138157
}
139158
}
140159

141-
return -1;
160+
return 0;
142161
}
143162

144163
int fsdev_wrapMountDevice(const char *name, const char* shortcut, FsFileSystem fs, bool own) {
164+
const size_t name_len = strlen(name);
165+
if (name_len <= 1 || name_len + 1 >= FsDevWrap_PATH_MAX) {
166+
errno = ENAMETOOLONG;
167+
return -1;
168+
}
169+
145170
for (int i = 0; i < FsDevWrap_DEVICES_MAX; i++) {
146171
if (!g_fsdev_entries[i].active) {
147172
g_fsdev_entries[i].active = true;

src/platform/nx/utils.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ extern "C" {
88

99
#include <switch.h>
1010

11+
#define FsDevWrap_DEVICES_MAX 32
12+
#define FsDevWrap_PATH_MAX 32
13+
1114
Result fsdev_wrapMountSdmc(void);
1215
Result fsdev_wrapMountImage(const char* path, FsImageDirectoryId id);
1316
Result fsdev_wrapMountContent(const char* path, FsContentStorageId id);

src/platform/nx/vfs_nx.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -674,9 +674,16 @@ int ftp_vfs_rmdir(const char* path) {
674674

675675
int ftp_vfs_rename(const char* src, const char* dst) {
676676
FsFileSystem* fs = NULL;
677+
FsFileSystem* fs_dst = NULL;
677678
char nxpath_src[FS_MAX_PATH];
678679
char nxpath_dst[FS_MAX_PATH];
679-
if (fsdev_wrapTranslatePath(src, &fs, nxpath_src) || fsdev_wrapTranslatePath(dst, NULL, nxpath_dst)) {
680+
if (fsdev_wrapTranslatePath(src, &fs, nxpath_src) || fsdev_wrapTranslatePath(dst, &fs_dst, nxpath_dst)) {
681+
return -1;
682+
}
683+
684+
// cannot rename across different fs.
685+
if (fs != fs_dst) {
686+
errno = EXDEV; // this will do for the error.
680687
return -1;
681688
}
682689

0 commit comments

Comments
 (0)