Use sdmc_dev

Enable UTF8
This commit is contained in:
mtheall 2015-08-19 13:25:34 -05:00
parent f1be81814c
commit 0ba3844ad8

View File

@ -1,29 +1,25 @@
#include "ftp.h" #include "ftp.h"
#include <arpa/inet.h> #include <arpa/inet.h>
#include <ctype.h> #include <ctype.h>
#include <dirent.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <malloc.h> #include <malloc.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <poll.h> #include <poll.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdio.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#ifdef _3DS #ifdef _3DS
#include <3ds.h> #include <3ds.h>
#else #define lstat stat
#include <dirent.h>
#include <sys/stat.h>
#endif #endif
#include "console.h" #include "console.h"
#ifndef _3DS
#define Errno() errno
#define closesocket(x) close(x)
#endif
#define POLL_UNKNOWN (~(POLLIN|POLLOUT)) #define POLL_UNKNOWN (~(POLLIN|POLLOUT))
#define XFER_BUFFERSIZE 4096 #define XFER_BUFFERSIZE 4096
@ -51,6 +47,7 @@ FTP_DECLARE(MKD);
FTP_DECLARE(MODE); FTP_DECLARE(MODE);
FTP_DECLARE(NLST); FTP_DECLARE(NLST);
FTP_DECLARE(NOOP); FTP_DECLARE(NOOP);
FTP_DECLARE(OPTS);
FTP_DECLARE(PASS); FTP_DECLARE(PASS);
FTP_DECLARE(PASV); FTP_DECLARE(PASV);
FTP_DECLARE(PORT); FTP_DECLARE(PORT);
@ -108,15 +105,11 @@ struct ftp_session_t
size_t buffersize; /*! persistent buffer size between callbacks */ size_t buffersize; /*! persistent buffer size between callbacks */
uint64_t filepos; /*! persistent file position between callbacks */ uint64_t filepos; /*! persistent file position between callbacks */
uint64_t filesize; /*! persistent file size between callbacks */ uint64_t filesize; /*! persistent file size between callbacks */
#ifdef _3DS
Handle fd; /*! persistent handle between callbacks */
#else
union union
{ {
DIR *dp; /*! persistent open directory pointer between callbacks */ DIR *dp; /*! persistent open directory pointer between callbacks */
int fd; /*! persistent open file descriptor between callbacks */ int fd; /*! persistent open file descriptor between callbacks */
}; };
#endif
}; };
/*! ftp command descriptor */ /*! ftp command descriptor */
@ -141,6 +134,7 @@ static ftp_command_t ftp_commands[] =
FTP_COMMAND(MODE), FTP_COMMAND(MODE),
FTP_COMMAND(NLST), FTP_COMMAND(NLST),
FTP_COMMAND(NOOP), FTP_COMMAND(NOOP),
FTP_COMMAND(OPTS),
FTP_COMMAND(PASS), FTP_COMMAND(PASS),
FTP_COMMAND(PASV), FTP_COMMAND(PASV),
FTP_COMMAND(PORT), FTP_COMMAND(PORT),
@ -165,16 +159,6 @@ static ftp_command_t ftp_commands[] =
/*! number of ftp commands */ /*! number of ftp commands */
static const size_t num_ftp_commands = sizeof(ftp_commands)/sizeof(ftp_commands[0]); static const size_t num_ftp_commands = sizeof(ftp_commands)/sizeof(ftp_commands[0]);
#ifdef _3DS
static inline int Errno(void)
{
int err = SOC_GetErrno();
if(err < 0)
return -err;
return err;
}
#endif
/*! compare ftp command descriptors /*! compare ftp command descriptors
* *
* @param[in] p1 left side of comparison (ftp_command_t*) * @param[in] p1 left side of comparison (ftp_command_t*)
@ -198,34 +182,6 @@ ftp_command_cmp(const void *p1,
#ifdef _3DS #ifdef _3DS
/*! SOC service buffer */ /*! SOC service buffer */
static u32 *SOC_buffer = NULL; static u32 *SOC_buffer = NULL;
/*! SDMC archive */
static FS_archive sdmcArchive =
{
.id = ARCH_SDMC,
.lowPath =
{
.type = PATH_EMPTY,
.size = 1,
.data = (u8*)"",
},
};
/*! convert 3DS dirent name to ASCII
*
* TODO: add support for non-ASCII characters
*
* @param[in] dst output buffer
* @param[in] src input buffer
*/
static void
convert_name(char *dst,
const u16 *src)
{
while(*src)
*dst++ = *src++;
*dst = 0;
}
#endif #endif
/*! server listen address */ /*! server listen address */
@ -233,9 +189,9 @@ static struct sockaddr_in serv_addr;
/*! listen file descriptor */ /*! listen file descriptor */
static int listenfd = -1; static int listenfd = -1;
/*! current data port */ /*! current data port */
in_port_t data_port = DATA_PORT; static in_port_t data_port = DATA_PORT;
/*! list of ftp sessions */ /*! list of ftp sessions */
ftp_session_t *sessions = NULL; static ftp_session_t *sessions = NULL;
/*! Allocate a new data port /*! Allocate a new data port
* *
@ -267,14 +223,14 @@ ftp_set_socket_nonblocking(int fd)
flags = fcntl(fd, F_GETFL, 0); flags = fcntl(fd, F_GETFL, 0);
if(flags == -1) if(flags == -1)
{ {
console_print(RED "fcntl: %d %s\n" RESET, Errno(), strerror(Errno())); console_print(RED "fcntl: %d %s\n" RESET, errno, strerror(errno));
return -1; return -1;
} }
rc = fcntl(fd, F_SETFL, flags | O_NONBLOCK); rc = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
if(rc != 0) if(rc != 0)
{ {
console_print(RED "fcntl: %d %s\n" RESET, Errno(), strerror(Errno())); console_print(RED "fcntl: %d %s\n" RESET, errno, strerror(errno));
return -1; return -1;
} }
@ -299,7 +255,7 @@ ftp_closesocket(int fd, int connected)
rc = getpeername(fd, (struct sockaddr*)&addr, &addrlen); rc = getpeername(fd, (struct sockaddr*)&addr, &addrlen);
if(rc != 0) if(rc != 0)
{ {
console_print(RED "getpeername: %d %s\n" RESET, Errno(), strerror(Errno())); console_print(RED "getpeername: %d %s\n" RESET, errno, strerror(errno));
console_print(YELLOW "closing connection to fd=%d\n" RESET, fd); console_print(YELLOW "closing connection to fd=%d\n" RESET, fd);
} }
else else
@ -309,13 +265,13 @@ ftp_closesocket(int fd, int connected)
/* shutdown connection */ /* shutdown connection */
rc = shutdown(fd, SHUT_RDWR); rc = shutdown(fd, SHUT_RDWR);
if(rc != 0) if(rc != 0)
console_print(RED "shutdown: %d %s\n" RESET, Errno(), strerror(Errno())); console_print(RED "shutdown: %d %s\n" RESET, errno, strerror(errno));
} }
/* close socket */ /* close socket */
rc = closesocket(fd); rc = close(fd);
if(rc != 0) if(rc != 0)
console_print(RED "closesocket: %d %s\n" RESET, Errno(), strerror(Errno())); console_print(RED "close: %d %s\n" RESET, errno, strerror(errno));
} }
/*! close command socket on ftp session /*! close command socket on ftp session
@ -367,21 +323,12 @@ ftp_session_close_data(ftp_session_t *session)
static void static void
ftp_session_close_file(ftp_session_t *session) ftp_session_close_file(ftp_session_t *session)
{ {
#ifdef _3DS
Result ret;
ret = FSFILE_Close(session->fd);
if(ret != 0)
console_print(RED "FSFILE_Close: 0x%08X\n" RESET, (unsigned int)ret);
session->fd = -1;
#else
int rc; int rc;
rc = close(session->fd); rc = close(session->fd);
if(rc != 0) if(rc != 0)
console_print(RED "close: %d %s\n" RESET, errno, strerror(errno)); console_print(RED "close: %d %s\n" RESET, errno, strerror(errno));
session->fd = -1; session->fd = -1;
#endif
} }
/*! open file for reading for ftp session /*! open file for reading for ftp session
@ -393,30 +340,6 @@ ftp_session_close_file(ftp_session_t *session)
static int static int
ftp_session_open_file_read(ftp_session_t *session) ftp_session_open_file_read(ftp_session_t *session)
{ {
#ifdef _3DS
Result ret;
u64 size;
/* open file in read mode */
ret = FSUSER_OpenFile(NULL, &session->fd, sdmcArchive,
FS_makePath(PATH_CHAR, session->buffer),
FS_OPEN_READ, FS_ATTRIBUTE_NONE);
if(ret != 0)
{
console_print(RED "FSUSER_OpenFile: 0x%08X\n" RESET, (unsigned int)ret);
return -1;
}
/* get the file size */
ret = FSFILE_GetSize(session->fd, &size);
if(ret != 0)
{
console_print(RED "FSFILE_GetSize: 0x%08X\n" RESET, (unsigned int)ret);
ftp_session_close_file(session);
return -1;
}
session->filesize = size;
#else
int rc; int rc;
struct stat st; struct stat st;
@ -437,7 +360,6 @@ ftp_session_open_file_read(ftp_session_t *session)
return -1; return -1;
} }
session->filesize = st.st_size; session->filesize = st.st_size;
#endif
/* reset file position */ /* reset file position */
/* TODO: support REST command */ /* TODO: support REST command */
@ -455,28 +377,9 @@ ftp_session_open_file_read(ftp_session_t *session)
static ssize_t static ssize_t
ftp_session_read_file(ftp_session_t *session) ftp_session_read_file(ftp_session_t *session)
{ {
#ifdef _3DS
Result ret;
u32 bytes;
/* read file at current position */
ret = FSFILE_Read(session->fd, &bytes, session->filepos,
session->buffer, sizeof(session->buffer));
if(ret != 0)
{
console_print(RED "FSFILE_Read: 0x%08X\n" RESET, (unsigned int)ret);
return -1;
}
/* adjust file position */
session->filepos += bytes;
return bytes;
#else
ssize_t rc; ssize_t rc;
/* read file at current position */ /* read file at current position */
/* TODO: maybe use pread? */
rc = read(session->fd, session->buffer, sizeof(session->buffer)); rc = read(session->fd, session->buffer, sizeof(session->buffer));
if(rc < 0) if(rc < 0)
{ {
@ -488,7 +391,6 @@ ftp_session_read_file(ftp_session_t *session)
session->filepos += rc; session->filepos += rc;
return rc; return rc;
#endif
} }
/*! open file for writing for ftp session /*! open file for writing for ftp session
@ -502,27 +404,6 @@ ftp_session_read_file(ftp_session_t *session)
static int static int
ftp_session_open_file_write(ftp_session_t *session) ftp_session_open_file_write(ftp_session_t *session)
{ {
#ifdef _3DS
Result ret;
/* open file in write and create mode */
ret = FSUSER_OpenFile(NULL, &session->fd, sdmcArchive,
FS_makePath(PATH_CHAR, session->buffer),
FS_OPEN_WRITE|FS_OPEN_CREATE, FS_ATTRIBUTE_NONE);
if(ret != 0)
{
console_print(RED "FSUSER_OpenFile: 0x%08X\n" RESET, (unsigned int)ret);
return -1;
}
/* truncate file */
ret = FSFILE_SetSize(session->fd, 0);
if(ret != 0)
{
console_print(RED "FSFILE_SetSize: 0x%08X\n" RESET, (unsigned int)ret);
ftp_session_close_file(session);
}
#else
/* open file in write and create mode with truncation */ /* open file in write and create mode with truncation */
session->fd = open(session->buffer, O_WRONLY|O_CREAT|O_TRUNC, 0644); session->fd = open(session->buffer, O_WRONLY|O_CREAT|O_TRUNC, 0644);
if(session->fd < 0) if(session->fd < 0)
@ -530,7 +411,6 @@ ftp_session_open_file_write(ftp_session_t *session)
console_print(RED "open '%s': %d %s\n" RESET, session->buffer, errno, strerror(errno)); console_print(RED "open '%s': %d %s\n" RESET, session->buffer, errno, strerror(errno));
return -1; return -1;
} }
#endif
/* reset file position */ /* reset file position */
/* TODO: support REST command */ /* TODO: support REST command */
@ -548,32 +428,9 @@ ftp_session_open_file_write(ftp_session_t *session)
static ssize_t static ssize_t
ftp_session_write_file(ftp_session_t *session) ftp_session_write_file(ftp_session_t *session)
{ {
#ifdef _3DS
Result ret;
u32 bytes;
/* write to file at current position */
ret = FSFILE_Write(session->fd, &bytes, session->filepos,
session->buffer + session->bufferpos,
session->buffersize - session->bufferpos,
FS_WRITE_FLUSH);
if(ret != 0)
{
console_print(RED "FSFILE_Write: 0x%08X\n" RESET, (unsigned int)ret);
return -1;
}
else if(bytes == 0)
console_print(RED "FSFILE_Write: wrote 0 bytes\n" RESET);
/* adjust file position */
session->filepos += bytes;
return bytes;
#else
ssize_t rc; ssize_t rc;
/* write to file at current position */ /* write to file at current position */
/* TODO: maybe use writev? */
rc = write(session->fd, session->buffer + session->bufferpos, rc = write(session->fd, session->buffer + session->bufferpos,
session->buffersize - session->bufferpos); session->buffersize - session->bufferpos);
if(rc < 0) if(rc < 0)
@ -588,7 +445,6 @@ ftp_session_write_file(ftp_session_t *session)
session->filepos += rc; session->filepos += rc;
return rc; return rc;
#endif
} }
/*! close current working directory for ftp session /*! close current working directory for ftp session
@ -598,15 +454,6 @@ ftp_session_write_file(ftp_session_t *session)
static void static void
ftp_session_close_cwd(ftp_session_t *session) ftp_session_close_cwd(ftp_session_t *session)
{ {
#ifdef _3DS
Result ret;
/* close open directory handle */
ret = FSDIR_Close(session->fd);
if(ret != 0)
console_print(RED "FSDIR_Close: 0x%08X\n" RESET, (unsigned int)ret);
session->fd = -1;
#else
int rc; int rc;
/* close open directory pointer */ /* close open directory pointer */
@ -614,7 +461,6 @@ ftp_session_close_cwd(ftp_session_t *session)
if(rc != 0) if(rc != 0)
console_print(RED "closedir: %d %s\n" RESET, errno, strerror(errno)); console_print(RED "closedir: %d %s\n" RESET, errno, strerror(errno));
session->dp = NULL; session->dp = NULL;
#endif
} }
/*! open current working directory for ftp session /*! open current working directory for ftp session
@ -626,18 +472,6 @@ ftp_session_close_cwd(ftp_session_t *session)
static int static int
ftp_session_open_cwd(ftp_session_t *session) ftp_session_open_cwd(ftp_session_t *session)
{ {
#ifdef _3DS
Result ret;
/* open current working directory */
ret = FSUSER_OpenDirectory(NULL, &session->fd, sdmcArchive,
FS_makePath(PATH_CHAR, session->cwd));
if(ret != 0)
{
console_print(RED "FSUSER_OpenDirectory: 0x%08X\n" RESET, (unsigned int)ret);
return -1;
}
#else
/* open current working directory */ /* open current working directory */
session->dp = opendir(session->cwd); session->dp = opendir(session->cwd);
if(session->dp == NULL) if(session->dp == NULL)
@ -645,7 +479,6 @@ ftp_session_open_cwd(ftp_session_t *session)
console_print(RED "opendir '%s': %d %s\n" RESET, session->cwd, errno, strerror(errno)); console_print(RED "opendir '%s': %d %s\n" RESET, session->cwd, errno, strerror(errno));
return -1; return -1;
} }
#endif
return 0; return 0;
} }
@ -715,7 +548,10 @@ ftp_send_response(ftp_session_t *session,
/* print response code and message to buffer */ /* print response code and message to buffer */
va_start(ap, fmt); va_start(ap, fmt);
if(code != 211)
rc = sprintf(buffer, "%d ", code); rc = sprintf(buffer, "%d ", code);
else
rc = sprintf(buffer, "%d- ", code);
rc += vsnprintf(buffer+rc, sizeof(buffer)-rc, fmt, ap); rc += vsnprintf(buffer+rc, sizeof(buffer)-rc, fmt, ap);
va_end(ap); va_end(ap);
@ -731,7 +567,7 @@ ftp_send_response(ftp_session_t *session,
console_print(GREEN "%s" RESET, buffer); console_print(GREEN "%s" RESET, buffer);
rc = send(session->cmd_fd, buffer, to_send, 0); rc = send(session->cmd_fd, buffer, to_send, 0);
if(rc < 0) if(rc < 0)
console_print(RED "send: %d %s\n" RESET, Errno(), strerror(Errno())); console_print(RED "send: %d %s\n" RESET, errno, strerror(errno));
else if(rc != to_send) else if(rc != to_send)
console_print(RED "only sent %u/%u bytes\n" RESET, console_print(RED "only sent %u/%u bytes\n" RESET,
(unsigned int)rc, (unsigned int)to_send); (unsigned int)rc, (unsigned int)to_send);
@ -742,8 +578,6 @@ ftp_send_response(ftp_session_t *session,
/*! destroy ftp session /*! destroy ftp session
* *
* @param[in] session ftp session * @param[in] session ftp session
*
* @returns next session in list
*/ */
static ftp_session_t* static ftp_session_t*
ftp_session_destroy(ftp_session_t *session) ftp_session_destroy(ftp_session_t *session)
@ -793,7 +627,7 @@ ftp_session_new(int listen_fd)
new_fd = accept(listen_fd, (struct sockaddr*)&addr, &addrlen); new_fd = accept(listen_fd, (struct sockaddr*)&addr, &addrlen);
if(new_fd < 0) if(new_fd < 0)
{ {
console_print(RED "accept: %d %s\n" RESET, Errno(), strerror(Errno())); console_print(RED "accept: %d %s\n" RESET, errno, strerror(errno));
return; return;
} }
@ -840,7 +674,7 @@ ftp_session_new(int listen_fd)
rc = getsockname(new_fd, (struct sockaddr*)&session->pasv_addr, &addrlen); rc = getsockname(new_fd, (struct sockaddr*)&session->pasv_addr, &addrlen);
if(rc != 0) if(rc != 0)
{ {
console_print(RED "getsockname: %d %s\n" RESET, Errno(), strerror(Errno())); console_print(RED "getsockname: %d %s\n" RESET, errno, strerror(errno));
ftp_send_response(session, 451, "Failed to get connection info\r\n"); ftp_send_response(session, 451, "Failed to get connection info\r\n");
ftp_session_destroy(session); ftp_session_destroy(session);
return; return;
@ -879,7 +713,7 @@ ftp_session_accept(ftp_session_t *session)
new_fd = accept(session->pasv_fd, (struct sockaddr*)&addr, &addrlen); new_fd = accept(session->pasv_fd, (struct sockaddr*)&addr, &addrlen);
if(new_fd < 0) if(new_fd < 0)
{ {
console_print(RED "accept: %d %s\n" RESET, Errno(), strerror(Errno())); console_print(RED "accept: %d %s\n" RESET, errno, strerror(errno));
ftp_session_set_state(session, COMMAND_STATE); ftp_session_set_state(session, COMMAND_STATE);
ftp_send_response(session, 425, "Failed to establish connection\r\n"); ftp_send_response(session, 425, "Failed to establish connection\r\n");
return -1; return -1;
@ -928,7 +762,7 @@ ftp_session_connect(ftp_session_t *session)
session->data_fd = socket(AF_INET, SOCK_STREAM, 0); session->data_fd = socket(AF_INET, SOCK_STREAM, 0);
if(session->data_fd < 0) if(session->data_fd < 0)
{ {
console_print(RED "socket: %d %s\n" RESET, Errno(), strerror(Errno())); console_print(RED "socket: %d %s\n" RESET, errno, strerror(errno));
return -1; return -1;
} }
@ -937,7 +771,7 @@ ftp_session_connect(ftp_session_t *session)
sizeof(session->peer_addr)); sizeof(session->peer_addr));
if(rc != 0) if(rc != 0)
{ {
console_print(RED "connect: %d %s\n" RESET, Errno(), strerror(Errno())); console_print(RED "connect: %d %s\n" RESET, errno, strerror(errno));
ftp_closesocket(session->data_fd, 0); ftp_closesocket(session->data_fd, 0);
session->data_fd = -1; session->data_fd = -1;
return -1; return -1;
@ -973,7 +807,7 @@ ftp_session_read_command(ftp_session_t *session)
if(rc < 0) if(rc < 0)
{ {
/* error retrieving command */ /* error retrieving command */
console_print(RED "recv: %d %s\n" RESET, Errno(), strerror(Errno())); console_print(RED "recv: %d %s\n" RESET, errno, strerror(errno));
ftp_session_close_cmd(session); ftp_session_close_cmd(session);
return; return;
} }
@ -1064,7 +898,7 @@ ftp_session_poll(ftp_session_t *session)
/* poll the selected socket */ /* poll the selected socket */
rc = poll(&pollinfo, 1, 0); rc = poll(&pollinfo, 1, 0);
if(rc < 0) if(rc < 0)
console_print(RED "poll: %d %s\n" RESET, Errno(), strerror(Errno())); console_print(RED "poll: %d %s\n" RESET, errno, strerror(errno));
else if(rc > 0) else if(rc > 0)
{ {
if(pollinfo.revents != 0) if(pollinfo.revents != 0)
@ -1142,15 +976,6 @@ ftp_init(void)
goto fs_fail; goto fs_fail;
} }
/* open SDMC archive */
ret = FSUSER_OpenArchive(NULL, &sdmcArchive);
if(ret != 0)
{
console_print(RED "FSUSER_OpenArchive: 0x%08X\n" RESET, (unsigned int)ret);
goto archive_fail;
}
#if ENABLE_LOGGING
/* initialize sdmc_dev */ /* initialize sdmc_dev */
ret = sdmcInit(); ret = sdmcInit();
if(ret != 0) if(ret != 0)
@ -1159,6 +984,7 @@ ftp_init(void)
goto sdmc_fail; goto sdmc_fail;
} }
#if ENABLE_LOGGING
/* open log file */ /* open log file */
FILE *fp = freopen("/ftbrony.log", "wb", stderr); FILE *fp = freopen("/ftbrony.log", "wb", stderr);
if(fp == NULL) if(fp == NULL)
@ -1196,7 +1022,7 @@ ftp_init(void)
listenfd = socket(AF_INET, SOCK_STREAM, 0); listenfd = socket(AF_INET, SOCK_STREAM, 0);
if(listenfd < 0) if(listenfd < 0)
{ {
console_print(RED "socket: %d %s\n" RESET, Errno(), strerror(Errno())); console_print(RED "socket: %d %s\n" RESET, errno, strerror(errno));
ftp_exit(); ftp_exit();
return -1; return -1;
} }
@ -1216,7 +1042,7 @@ ftp_init(void)
rc = setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)); rc = setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
if(rc != 0) if(rc != 0)
{ {
console_print(RED "setsockopt: %d %s\n" RESET, Errno(), strerror(Errno())); console_print(RED "setsockopt: %d %s\n" RESET, errno, strerror(errno));
ftp_exit(); ftp_exit();
return -1; return -1;
} }
@ -1227,7 +1053,7 @@ ftp_init(void)
rc = bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); rc = bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
if(rc != 0) if(rc != 0)
{ {
console_print(RED "bind: %d %s\n" RESET, Errno(), strerror(Errno())); console_print(RED "bind: %d %s\n" RESET, errno, strerror(errno));
ftp_exit(); ftp_exit();
return -1; return -1;
} }
@ -1236,7 +1062,7 @@ ftp_init(void)
rc = listen(listenfd, 5); rc = listen(listenfd, 5);
if(rc != 0) if(rc != 0)
{ {
console_print(RED "listen: %d %s\n" RESET, Errno(), strerror(Errno())); console_print(RED "listen: %d %s\n" RESET, errno, strerror(errno));
ftp_exit(); ftp_exit();
return -1; return -1;
} }
@ -1256,7 +1082,7 @@ ftp_init(void)
rc = getsockname(listenfd, (struct sockaddr*)&serv_addr, &addrlen); rc = getsockname(listenfd, (struct sockaddr*)&serv_addr, &addrlen);
if(rc != 0) if(rc != 0)
{ {
console_print(RED "getsockname: %d %s\n" RESET, Errno(), strerror(Errno())); console_print(RED "getsockname: %d %s\n" RESET, errno, strerror(errno));
ftp_exit(); ftp_exit();
return -1; return -1;
} }
@ -1264,7 +1090,7 @@ ftp_init(void)
rc = gethostname(hostname, sizeof(hostname)); rc = gethostname(hostname, sizeof(hostname));
if(rc != 0) if(rc != 0)
{ {
console_print(RED "gethostname: %d %s\n" RESET, Errno(), strerror(Errno())); console_print(RED "gethostname: %d %s\n" RESET, errno, strerror(errno));
ftp_exit(); ftp_exit();
return -1; return -1;
} }
@ -1291,17 +1117,12 @@ ftruncate_fail:
console_print(RED "fclose: 0x%08X\n" RESET, errno); console_print(RED "fclose: 0x%08X\n" RESET, errno);
stderr_fail: stderr_fail:
#endif
ret = sdmcExit(); ret = sdmcExit();
if(ret != 0) if(ret != 0)
console_print(RED "sdmcExit: 0x%08X\n" RESET, (unsigned int)ret); console_print(RED "sdmcExit: 0x%08X\n" RESET, (unsigned int)ret);
sdmc_fail: sdmc_fail:
#endif
ret = FSUSER_CloseArchive(NULL, &sdmcArchive);
if(ret != 0)
console_print(RED "FSUSER_CloseArchive: 0x%08X\n" RESET, (unsigned int)ret);
archive_fail:
ret = fsExit(); ret = fsExit();
if(ret != 0) if(ret != 0)
console_print(RED "fsExit: 0x%08X\n" RESET, (unsigned int)ret); console_print(RED "fsExit: 0x%08X\n" RESET, (unsigned int)ret);
@ -1365,7 +1186,10 @@ ftp_loop(void)
rc = poll(&pollinfo, 1, 0); rc = poll(&pollinfo, 1, 0);
if(rc < 0) if(rc < 0)
console_print(RED "poll: %d %s\n" RESET, Errno(), strerror(Errno())); {
console_print(RED "poll: %d %s\n" RESET, errno, strerror(errno));
return -1;
}
else if(rc > 0) else if(rc > 0)
{ {
if(pollinfo.revents & POLLIN) if(pollinfo.revents & POLLIN)
@ -1479,47 +1303,10 @@ build_path(ftp_session_t *session,
static int static int
list_transfer(ftp_session_t *session) list_transfer(ftp_session_t *session)
{ {
#ifdef _3DS
Result ret;
#endif
ssize_t rc; ssize_t rc;
if(session->bufferpos == session->buffersize) if(session->bufferpos == session->buffersize)
{ {
#ifdef _3DS
FS_dirent dent;
u32 entries;
char name[256];
ret = FSDIR_Read(session->fd, &entries, 1, &dent);
if(ret != 0)
{
console_print(RED "FSDIR_Read: 0x%08X\n" RESET, (unsigned int)ret);
ftp_session_close_cwd(session);
ftp_session_set_state(session, COMMAND_STATE);
ftp_send_response(session, 450, "failed to read directory\r\n");
return -1;
}
if(entries == 0)
{
ftp_session_close_cwd(session);
ftp_session_set_state(session, COMMAND_STATE);
ftp_send_response(session, 226, "OK\r\n");
return -1;
}
convert_name(name, dent.name);
if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0)
return 0;
session->buffersize =
sprintf(session->buffer,
"%crwxrwxrwx 1 3DS 3DS %llu Jan 1 1970 %s\r\n",
dent.isDirectory ? 'd' : '-',
dent.fileSize,
name);
#else
struct stat st; struct stat st;
struct dirent *dent = readdir(session->dp); struct dirent *dent = readdir(session->dp);
if(dent == NULL) if(dent == NULL)
@ -1533,6 +1320,10 @@ list_transfer(ftp_session_t *session)
if(strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0) if(strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0)
return 0; return 0;
if(strcmp(session->cwd, "/") == 0)
snprintf(session->buffer, sizeof(session->buffer),
"/%s", dent->d_name);
else
snprintf(session->buffer, sizeof(session->buffer), snprintf(session->buffer, sizeof(session->buffer),
"%s/%s", session->cwd, dent->d_name); "%s/%s", session->cwd, dent->d_name);
rc = lstat(session->buffer, &st); rc = lstat(session->buffer, &st);
@ -1552,7 +1343,6 @@ list_transfer(ftp_session_t *session)
S_ISLNK(st.st_mode) ? 'l' : '-', S_ISLNK(st.st_mode) ? 'l' : '-',
(unsigned long long)st.st_size, (unsigned long long)st.st_size,
dent->d_name); dent->d_name);
#endif
session->bufferpos = 0; session->bufferpos = 0;
} }
@ -1562,9 +1352,9 @@ list_transfer(ftp_session_t *session)
{ {
if(rc < 0) if(rc < 0)
{ {
if(Errno() == EWOULDBLOCK) if(errno == EWOULDBLOCK)
return -1; return -1;
console_print(RED "send: %d %s\n" RESET, Errno(), strerror(Errno())); console_print(RED "send: %d %s\n" RESET, errno, strerror(errno));
} }
else else
console_print(YELLOW "send: %d %s\n" RESET, ECONNRESET, strerror(ECONNRESET)); console_print(YELLOW "send: %d %s\n" RESET, ECONNRESET, strerror(ECONNRESET));
@ -1608,9 +1398,9 @@ retrieve_transfer(ftp_session_t *session)
{ {
if(rc < 0) if(rc < 0)
{ {
if(Errno() == EWOULDBLOCK) if(errno == EWOULDBLOCK)
return -1; return -1;
console_print(RED "send: %d %s\n" RESET, Errno(), strerror(Errno())); console_print(RED "send: %d %s\n" RESET, errno, strerror(errno));
} }
else else
console_print(YELLOW "send: %d %s\n" RESET, ECONNRESET, strerror(ECONNRESET)); console_print(YELLOW "send: %d %s\n" RESET, ECONNRESET, strerror(ECONNRESET));
@ -1637,9 +1427,9 @@ store_transfer(ftp_session_t *session)
{ {
if(rc < 0) if(rc < 0)
{ {
if(Errno() == EWOULDBLOCK) if(errno == EWOULDBLOCK)
return -1; return -1;
console_print(RED "recv: %d %s\n" RESET, Errno(), strerror(Errno())); console_print(RED "recv: %d %s\n" RESET, errno, strerror(errno));
} }
ftp_session_close_file(session); ftp_session_close_file(session);
@ -1723,19 +1513,6 @@ FTP_DECLARE(CWD)
return ftp_send_response(session, 553, "%s\r\n", strerror(errno)); return ftp_send_response(session, 553, "%s\r\n", strerror(errno));
{ {
#ifdef _3DS
Result ret;
Handle fd;
ret = FSUSER_OpenDirectory(NULL, &fd, sdmcArchive,
FS_makePath(PATH_CHAR, session->buffer));
if(ret != 0)
return ftp_send_response(session, 553, "not a directory\r\n");
ret = FSDIR_Close(fd);
if(ret != 0)
console_print(RED "FSDIR_Close: 0x%08X\n" RESET, (unsigned int)ret);
#else
struct stat st; struct stat st;
int rc; int rc;
@ -1748,7 +1525,6 @@ FTP_DECLARE(CWD)
if(!S_ISDIR(st.st_mode)) if(!S_ISDIR(st.st_mode))
return ftp_send_response(session, 553, "not a directory\r\n"); return ftp_send_response(session, 553, "not a directory\r\n");
#endif
} }
strncpy(session->cwd, session->buffer, sizeof(session->cwd)); strncpy(session->cwd, session->buffer, sizeof(session->cwd));
@ -1758,11 +1534,7 @@ FTP_DECLARE(CWD)
FTP_DECLARE(DELE) FTP_DECLARE(DELE)
{ {
#ifdef _3DS
Result ret;
#else
int rc; int rc;
#endif
console_print(CYAN "%s %s\n" RESET, __func__, args ? args : ""); console_print(CYAN "%s %s\n" RESET, __func__, args ? args : "");
@ -1771,21 +1543,12 @@ FTP_DECLARE(DELE)
if(build_path(session, args) != 0) if(build_path(session, args) != 0)
return ftp_send_response(session, 553, "%s\r\n", strerror(errno)); return ftp_send_response(session, 553, "%s\r\n", strerror(errno));
#ifdef _3DS
ret = FSUSER_DeleteFile(NULL, sdmcArchive, FS_makePath(PATH_CHAR, session->buffer));
if(ret != 0)
{
console_print(RED "FSUSER_DeleteFile: 0x%08X\n" RESET, (unsigned int)ret);
return ftp_send_response(session, 550, "failed to delete file\r\n");
}
#else
rc = unlink(session->buffer); rc = unlink(session->buffer);
if(rc != 0) if(rc != 0)
{ {
console_print(RED "unlink: %d %s\n" RESET, errno, strerror(errno)); console_print(RED "unlink: %d %s\n" RESET, errno, strerror(errno));
return ftp_send_response(session, 550, "failed to delete file\r\n"); return ftp_send_response(session, 550, "failed to delete file\r\n");
} }
#endif
return ftp_send_response(session, 250, "OK\r\n"); return ftp_send_response(session, 250, "OK\r\n");
} }
@ -1796,7 +1559,7 @@ FTP_DECLARE(FEAT)
ftp_session_set_state(session, COMMAND_STATE); ftp_session_set_state(session, COMMAND_STATE);
return ftp_send_response(session, 211, "\r\n"); return ftp_send_response(session, 211, "\r\n UTF8\r\n211 End\r\n");
} }
FTP_DECLARE(LIST) FTP_DECLARE(LIST)
@ -1849,11 +1612,7 @@ FTP_DECLARE(LIST)
FTP_DECLARE(MKD) FTP_DECLARE(MKD)
{ {
#ifdef _3DS
Result ret;
#else
int rc; int rc;
#endif
console_print(CYAN "%s %s\n" RESET, __func__, args ? args : ""); console_print(CYAN "%s %s\n" RESET, __func__, args ? args : "");
@ -1862,21 +1621,12 @@ FTP_DECLARE(MKD)
if(build_path(session, args) != 0) if(build_path(session, args) != 0)
return ftp_send_response(session, 553, "%s\r\n", strerror(errno)); return ftp_send_response(session, 553, "%s\r\n", strerror(errno));
#ifdef _3DS
ret = FSUSER_CreateDirectory(NULL, sdmcArchive, FS_makePath(PATH_CHAR, session->buffer));
if(ret != 0)
{
console_print(RED "FSUSER_OpenDirectory: 0x%08X\n" RESET, (unsigned int)ret);
return ftp_send_response(session, 550, "failed to create directory\r\n");
}
#else
rc = mkdir(session->buffer, 0755); rc = mkdir(session->buffer, 0755);
if(rc != 0) if(rc != 0)
{ {
console_print(RED "mkdir: %d %s\n" RESET, errno, strerror(errno)); console_print(RED "mkdir: %d %s\n" RESET, errno, strerror(errno));
return ftp_send_response(session, 550, "failed to create directory\r\n"); return ftp_send_response(session, 550, "failed to create directory\r\n");
} }
#endif
return ftp_send_response(session, 250, "OK\r\n"); return ftp_send_response(session, 250, "OK\r\n");
} }
@ -1909,6 +1659,20 @@ FTP_DECLARE(NOOP)
return ftp_send_response(session, 200, "OK\r\n"); return ftp_send_response(session, 200, "OK\r\n");
} }
FTP_DECLARE(OPTS)
{
console_print(CYAN "%s %s\n" RESET, __func__, args ? args : "");
ftp_session_set_state(session, COMMAND_STATE);
if(strcasecmp(args, "UTF8") == 0
|| strcasecmp(args, "UTF8 ON") == 0
|| strcasecmp(args, "UTF8 NLST") == 0)
return ftp_send_response(session, 200, "OK\r\n");
return ftp_send_response(session, 504, "invalid argument\r\n");
}
FTP_DECLARE(PASS) FTP_DECLARE(PASS)
{ {
console_print(CYAN "%s %s\n" RESET, __func__, args ? args : ""); console_print(CYAN "%s %s\n" RESET, __func__, args ? args : "");
@ -1936,7 +1700,7 @@ FTP_DECLARE(PASV)
session->pasv_fd = socket(AF_INET, SOCK_STREAM, 0); session->pasv_fd = socket(AF_INET, SOCK_STREAM, 0);
if(session->pasv_fd < 0) if(session->pasv_fd < 0)
{ {
console_print(RED "socket: %d %s\n" RESET, Errno(), strerror(Errno())); console_print(RED "socket: %d %s\n" RESET, errno, strerror(errno));
return ftp_send_response(session, 451, "\r\n"); return ftp_send_response(session, 451, "\r\n");
} }
@ -1951,7 +1715,7 @@ FTP_DECLARE(PASV)
sizeof(session->pasv_addr)); sizeof(session->pasv_addr));
if(rc != 0) if(rc != 0)
{ {
console_print(RED "bind: %d %s\n" RESET, Errno(), strerror(Errno())); console_print(RED "bind: %d %s\n" RESET, errno, strerror(errno));
ftp_session_close_pasv(session); ftp_session_close_pasv(session);
return ftp_send_response(session, 451, "\r\n"); return ftp_send_response(session, 451, "\r\n");
} }
@ -1959,7 +1723,7 @@ FTP_DECLARE(PASV)
rc = listen(session->pasv_fd, 5); rc = listen(session->pasv_fd, 5);
if(rc != 0) if(rc != 0)
{ {
console_print(RED "listen: %d %s\n" RESET, Errno(), strerror(Errno())); console_print(RED "listen: %d %s\n" RESET, errno, strerror(errno));
ftp_session_close_pasv(session); ftp_session_close_pasv(session);
return ftp_send_response(session, 451, "\r\n"); return ftp_send_response(session, 451, "\r\n");
} }
@ -1971,7 +1735,7 @@ FTP_DECLARE(PASV)
&addrlen); &addrlen);
if(rc != 0) if(rc != 0)
{ {
console_print(RED "getsockname: %d %s\n" RESET, Errno(), strerror(Errno())); console_print(RED "getsockname: %d %s\n" RESET, errno, strerror(errno));
ftp_session_close_pasv(session); ftp_session_close_pasv(session);
return ftp_send_response(session, 451, "\r\n"); return ftp_send_response(session, 451, "\r\n");
} }
@ -2171,11 +1935,7 @@ FTP_DECLARE(RETR)
FTP_DECLARE(RMD) FTP_DECLARE(RMD)
{ {
#ifdef _3DS
Result ret;
#else
int rc; int rc;
#endif
console_print(CYAN "%s %s\n" RESET, __func__, args ? args : ""); console_print(CYAN "%s %s\n" RESET, __func__, args ? args : "");
@ -2184,34 +1944,20 @@ FTP_DECLARE(RMD)
if(build_path(session, args) != 0) if(build_path(session, args) != 0)
return ftp_send_response(session, 553, "%s\r\n", strerror(errno)); return ftp_send_response(session, 553, "%s\r\n", strerror(errno));
#ifdef _3DS
ret = FSUSER_DeleteDirectory(NULL, sdmcArchive, FS_makePath(PATH_CHAR, session->buffer));
if(ret != 0)
{
console_print(RED "FSUSER_DeleteDirectory: 0x%08X\n" RESET, (unsigned int)ret);
return ftp_send_response(session, 550, "failed to delete directory\r\n");
}
#else
rc = rmdir(session->buffer); rc = rmdir(session->buffer);
if(rc != 0) if(rc != 0)
{ {
console_print(RED "rmdir: %d %s\n" RESET, errno, strerror(errno)); console_print(RED "rmdir: %d %s\n" RESET, errno, strerror(errno));
return ftp_send_response(session, 550, "failed to delete directory\r\n"); return ftp_send_response(session, 550, "failed to delete directory\r\n");
} }
#endif
return ftp_send_response(session, 250, "OK\r\n"); return ftp_send_response(session, 250, "OK\r\n");
} }
FTP_DECLARE(RNFR) FTP_DECLARE(RNFR)
{ {
#ifdef _3DS
Result ret;
Handle fd;
#else
int rc; int rc;
struct stat st; struct stat st;
#endif
console_print(CYAN "%s %s\n" RESET, __func__, args ? args : ""); console_print(CYAN "%s %s\n" RESET, __func__, args ? args : "");
ftp_session_set_state(session, COMMAND_STATE); ftp_session_set_state(session, COMMAND_STATE);
@ -2219,35 +1965,12 @@ FTP_DECLARE(RNFR)
if(build_path(session, args) != 0) if(build_path(session, args) != 0)
return ftp_send_response(session, 553, "%s\r\n", strerror(errno)); return ftp_send_response(session, 553, "%s\r\n", strerror(errno));
#ifdef _3DS
ret = FSUSER_OpenFile(NULL, &fd, sdmcArchive,
FS_makePath(PATH_CHAR, session->buffer),
FS_OPEN_READ, FS_ATTRIBUTE_NONE);
if(ret != 0)
{
ret = FSUSER_OpenDirectory(NULL, &fd, sdmcArchive,
FS_makePath(PATH_CHAR, session->buffer));
if(ret == 0)
ret = FSDIR_Close(fd);
}
else
{
ret = FSFILE_Close(fd);
}
if(ret != 0)
{
console_print(RED "no such file or directory\n" RESET);
return ftp_send_response(session, 450, "no such file or directory\r\n");
}
#else
rc = lstat(session->buffer, &st); rc = lstat(session->buffer, &st);
if(rc != 0) if(rc != 0)
{ {
console_print(RED "lstat: %d %s\n" RESET, errno, strerror(errno)); console_print(RED "lstat: %d %s\n" RESET, errno, strerror(errno));
return ftp_send_response(session, 450, "no such file or directory\r\n"); return ftp_send_response(session, 450, "no such file or directory\r\n");
} }
#endif
session->flags |= SESSION_RENAME; session->flags |= SESSION_RENAME;
@ -2256,11 +1979,7 @@ FTP_DECLARE(RNFR)
FTP_DECLARE(RNTO) FTP_DECLARE(RNTO)
{ {
#ifdef _3DS
Result ret;
#else
int rc; int rc;
#endif
char buffer[XFER_BUFFERSIZE]; char buffer[XFER_BUFFERSIZE];
console_print(CYAN "%s %s\n" RESET, __func__, args ? args : ""); console_print(CYAN "%s %s\n" RESET, __func__, args ? args : "");
@ -2277,27 +1996,12 @@ FTP_DECLARE(RNTO)
if(build_path(session, args) != 0) if(build_path(session, args) != 0)
return ftp_send_response(session, 554, "%s\r\n", strerror(errno)); return ftp_send_response(session, 554, "%s\r\n", strerror(errno));
#ifdef _3DS
ret = FSUSER_RenameFile(NULL,
sdmcArchive, FS_makePath(PATH_CHAR, buffer),
sdmcArchive, FS_makePath(PATH_CHAR, session->buffer));
if(ret != 0)
ret = FSUSER_RenameDirectory(NULL,
sdmcArchive, FS_makePath(PATH_CHAR, buffer),
sdmcArchive, FS_makePath(PATH_CHAR, session->buffer));
if(ret != 0)
{
console_print(RED "FSUSER_RenameFile/Directory: 0x%08X\n" RESET, (unsigned int)ret);
return ftp_send_response(session, 550, "failed to rename file/directory\r\n");
}
#else
rc = rename(buffer, session->buffer); rc = rename(buffer, session->buffer);
if(rc != 0) if(rc != 0)
{ {
console_print(RED "rename: %d %s\n" RESET, errno, strerror(errno)); console_print(RED "rename: %d %s\n" RESET, errno, strerror(errno));
return ftp_send_response(session, 550, "failed to rename file/directory\r\n"); return ftp_send_response(session, 550, "failed to rename file/directory\r\n");
} }
#endif
return ftp_send_response(session, 250, "OK\r\n"); return ftp_send_response(session, 250, "OK\r\n");
} }