diff --git a/Makefile.3ds b/Makefile.3ds index fc3d5c7..cc6c675 100644 --- a/Makefile.3ds +++ b/Makefile.3ds @@ -44,7 +44,7 @@ ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard CFLAGS := -g -Wall -O3 -mword-relocations \ -fomit-frame-pointer -ffast-math \ $(ARCH) \ - -DSTATUS_STRING="\"ftbrony v1.0\"" + -DSTATUS_STRING="\"ftbrony v1.1\"" CFLAGS += $(INCLUDE) -DARM11 -D_3DS diff --git a/data/sans.10.kerning.bin b/data/sans.10.kerning.bin deleted file mode 100644 index f6b70eb..0000000 Binary files a/data/sans.10.kerning.bin and /dev/null differ diff --git a/data/sans.10.render.bin b/data/sans.10.render.bin deleted file mode 100644 index 08da873..0000000 Binary files a/data/sans.10.render.bin and /dev/null differ diff --git a/data/sans.12.kerning.bin b/data/sans.12.kerning.bin deleted file mode 100644 index 843d796..0000000 Binary files a/data/sans.12.kerning.bin and /dev/null differ diff --git a/data/sans.12.render.bin b/data/sans.12.render.bin deleted file mode 100644 index 74912e9..0000000 Binary files a/data/sans.12.render.bin and /dev/null differ diff --git a/data/sans.14.kerning.bin b/data/sans.14.kerning.bin deleted file mode 100644 index e89a9fe..0000000 Binary files a/data/sans.14.kerning.bin and /dev/null differ diff --git a/data/sans.14.render.bin b/data/sans.14.render.bin deleted file mode 100644 index c5b6d09..0000000 Binary files a/data/sans.14.render.bin and /dev/null differ diff --git a/data/sans.16.kerning.bin b/data/sans.16.kerning.bin deleted file mode 100644 index be40c26..0000000 Binary files a/data/sans.16.kerning.bin and /dev/null differ diff --git a/data/sans.16.render.bin b/data/sans.16.render.bin deleted file mode 100644 index a93c756..0000000 Binary files a/data/sans.16.render.bin and /dev/null differ diff --git a/data/sans.8.kerning.bin b/data/sans.8.kerning.bin deleted file mode 100644 index f95aff5..0000000 Binary files a/data/sans.8.kerning.bin and /dev/null differ diff --git a/data/sans.8.render.bin b/data/sans.8.render.bin deleted file mode 100644 index 9d1dd7c..0000000 Binary files a/data/sans.8.render.bin and /dev/null differ diff --git a/include/console.h b/include/console.h index 3abc432..77a5884 100644 --- a/include/console.h +++ b/include/console.h @@ -1,7 +1,17 @@ #pragma once +#define ESC(x) "\x1b[" #x +#define RESET ESC(0m) +#define BLACK ESC(30m) +#define RED ESC(31;1m) +#define GREEN ESC(32;1m) +#define YELLOW ESC(33;1m) +#define BLUE ESC(34;1m) +#define MAGENTA ESC(35;1m) +#define CYAN ESC(36;1m) +#define WHITE ESC(37;1m) + void console_init(void); -void console_exit(void); __attribute__((format(printf,1,2))) void console_set_status(const char *fmt, ...); diff --git a/include/gfx.h b/include/gfx.h index 58b1e0a..7234f26 100755 --- a/include/gfx.h +++ b/include/gfx.h @@ -1,3 +1,8 @@ #pragma once -void gfxDrawSprite(gfxScreen_t screen, gfx3dSide_t side, u8* spriteData, u16 width, u16 height, s16 x, s16 y); \ No newline at end of file +#ifdef _3DS +#include <3ds.h> + +void gfxDrawSprite(gfxScreen_t screen, gfx3dSide_t side, u8* spriteData, u16 width, u16 height, s16 x, s16 y); + +#endif diff --git a/source/console.c b/source/console.c index 86c1ae3..834c37a 100644 --- a/source/console.c +++ b/source/console.c @@ -9,321 +9,24 @@ #include "gfx.h" #ifdef _3DS -#include "sans_8_kerning_bin.h" -#include "sans_8_render_bin.h" -#include "sans_10_kerning_bin.h" -#include "sans_10_render_bin.h" -#include "sans_12_kerning_bin.h" -#include "sans_12_render_bin.h" -#include "sans_14_kerning_bin.h" -#include "sans_14_render_bin.h" -#include "sans_16_kerning_bin.h" -#include "sans_16_render_bin.h" #include "banner_bin.h" -/* TODO: add support for non-ASCII characters */ - -/*! rendering information */ -typedef struct -{ - int c; /*!< character */ - int y_off; /*!< vertical offset */ - int width; /*!< width */ - int height; /*!< height */ - int x_adv; /*!< horizontal advance */ - u8 data[]; /*!< width*height bitmap */ -} render_info_t; - -/*! kerning information */ -typedef struct -{ - int prev; /*!< previous character */ - int next; /*!< next character */ - int x_off; /*!< horizontal adjustment */ -} kerning_info_t; - -/*! font data */ -typedef struct -{ - const char *name; /*!< font name */ - render_info_t **render_info; /*!< render information list */ - kerning_info_t *kerning_info; /*!< kerning information list */ - size_t num_render_info; /*!< number of render information nodes */ - size_t num_kerning_info; /*!< number of kerning information nodes */ - int pt; /*!< font size */ -} font_t; - -/*! font information */ -typedef struct -{ - const char *name; /*!< font name */ - int pt; /*!< font size */ - const u8 *render_data; /*!< render data */ - const u8 *kerning_data; /*!< kerning data */ - const u32 *render_data_size; /*!< render data size */ - const u32 *kerning_data_size; /*!< kerning data size */ -} font_info_t; - -/*! font descriptors */ -static font_info_t font_info[] = -{ -#define FONT_INFO(name, pt) \ - { #name, pt, name##_##pt##_render_bin, name##_##pt##_kerning_bin, \ - &name##_##pt##_render_bin_size, &name##_##pt##_kerning_bin_size, } - FONT_INFO(sans, 8), - FONT_INFO(sans, 10), - FONT_INFO(sans, 12), - FONT_INFO(sans, 14), - FONT_INFO(sans, 16), -}; -/*! number of font descriptors */ -static const size_t num_font_info = sizeof(font_info)/sizeof(font_info[0]); - -/*! find next render info - * - * @param[in] info current render info - * - * @returns next render info - */ -static render_info_t* -next_render_info(render_info_t *info) -{ - char *ptr = (char*)info; - ptr += sizeof(*info) + info->width*info->height; - ptr = (char*)(((int)ptr + sizeof(int)-1) & ~(sizeof(int)-1)); - - return (render_info_t*)ptr; -} - -/*! free font info - * - * @param[in] font - */ -static void -free_font(font_t *font) -{ - free(font->render_info); - free(font); -} - -/*! load font info - * - * @param[in] name - * @param[in] pt - * @param[in] render_data - * @param[in] render_data_size - * @param[in] kerning data - * @param[in] kerning_data_size - * - * @returns font info - */ -static font_t* -load_font(const char *name, - int pt, - const u8 *render_data, - size_t render_data_size, - const u8 *kerning_data, - size_t kerning_data_size) -{ - size_t i; - render_info_t *rinfo; - font_t *font; - - /* allocate new font info */ - font = (font_t*)calloc(1, sizeof(font_t)); - if(font != NULL) - { - /* count number of render entries */ - rinfo = (render_info_t*)render_data; - while((u8*)rinfo < render_data + render_data_size) - { - ++font->num_render_info; - rinfo = next_render_info(rinfo); - } - - /* allocate array of render info pointers */ - font->render_info = (render_info_t**)calloc(font->num_render_info, sizeof(render_info_t)); - if(font->render_info != NULL) - { - /* fill in the pointer list */ - rinfo = (render_info_t*)render_data; - i = 0; - while((u8*)rinfo < render_data + render_data_size) - { - font->render_info[i++] = rinfo; - rinfo = next_render_info(rinfo); - } - - /* fill in the kerning info */ - font->kerning_info = (kerning_info_t*)kerning_data; - font->num_kerning_info = kerning_data_size / sizeof(kerning_info_t); - - /* set font size and name */ - font->pt = pt; - font->name = name; - } - else - { - /* failed to allocate render info list */ - free_font(font); - font = NULL; - } - } - - return font; -} - -/*! list of font info entries */ -static font_t **fonts; -/*! number of font info entries */ -static size_t num_fonts = 0; - -/*! compare two fonts - * - * @param[in] p1 left side of comparison (font_t**) - * @param[in] p2 right side of comparison (font_t**) - * - * @returns <0 if p1 < p2 - * @returns 0 if p1 == p2 - * @returns >0 if p1 > p2 - */ -static int -font_cmp(const void *p1, - const void *p2) -{ - /* interpret parameters */ - font_t *f1 = *(font_t**)p1; - font_t *f2 = *(font_t**)p2; - - /* major key is font name */ - int rc = strcmp(f1->name, f2->name); - if(rc != 0) - return rc; - - /* minor key is font size */ - if(f1->pt < f2->pt) - return -1; - if(f1->pt > f2->pt) - return 1; - return 0; -} - -/*! search for a font by name and size - * - * @param[in] name font name - * @param[in] pt font size - * - * @returns matching font - */ -static font_t* -find_font(const char *name, - int pt) -{ - /* create a key to search for */ - font_t key, *keyptr; - key.name = name; - key.pt = pt; - keyptr = &key; - - /* search for the key */ - void *font = bsearch(&keyptr, fonts, num_fonts, sizeof(font_t*), font_cmp); - if(font == NULL) - return NULL; - - /* found it */ - return *(font_t**)font; -} +static PrintConsole status_console; +static PrintConsole main_console; /*! initialize console subsystem */ void console_init(void) { - size_t i; + consoleInit(GFX_TOP, &status_console); + consoleSetWindow(&status_console, 0, 0, 50, 1); - /* allocate font list */ - fonts = (font_t**)calloc(num_font_info, sizeof(font_t*)); - if(fonts == NULL) - return; + consoleInit(GFX_TOP, &main_console); + consoleSetWindow(&main_console, 0, 1, 50, 29); - /* load fonts */ - for(i = 0; i < num_font_info; ++i) - { - font_info_t *info = &font_info[i]; - fonts[num_fonts] = load_font(info->name, info->pt, - info->render_data, - *info->render_data_size, - info->kerning_data, - *info->kerning_data_size); - if(fonts[num_fonts] != NULL) - ++num_fonts; - } + consoleSelect(&main_console); - /* sort the list for bsearch later */ - qsort(fonts, num_fonts, sizeof(font_t*), font_cmp); -} - -/*! deinitialize console subsystem */ -void -console_exit(void) -{ - int i; - - /* free the font info */ - for(i = 0; i < num_fonts; ++i) - free_font(fonts[i]); - - /* free the font info list */ - free(fonts); - fonts = NULL; -} - -/*! status bar contents */ -static char status[64]; -/*! console buffer */ -static char buffer[8192]; -/*! pointer to end of buffer */ -static char *buffer_end = buffer + sizeof(buffer); -/*! pointer to end of console contents */ -static char *end = buffer; - -/*! count lines in console contents */ -static size_t -count_lines(void) -{ - size_t lines = 0; - char *p = buffer; - - /* search for each newline character */ - while(p < end && (p = strchr(p, '\n')) != NULL) - { - ++lines; - ++p; - } - - return lines; -} - -/*! remove lines that have "scrolled" off screen */ -static void -reduce_lines(void) -{ - int lines = count_lines(); - char *p = buffer; - - /* we can fit 18 lines on the screen */ - /* TODO make based on pt size */ - while(lines > 18) - { - p = strchr(p, '\n'); - ++p; - --lines; - } - - /* move the new beginning to where it needs to be */ - ptrdiff_t distance = p - buffer; - memmove(buffer, buffer+distance, end - p); - end -= distance; - *end = 0; + consoleDebugInit(debugDevice_NULL); } /*! set status bar contents @@ -336,10 +39,12 @@ console_set_status(const char *fmt, ...) { va_list ap; + consoleSelect(&status_console); va_start(ap, fmt); - memset(status, 0, sizeof(status)); - vsnprintf(status, sizeof(status)-1, fmt, ap); + vprintf(fmt, ap); + vfprintf(stderr, fmt, ap); va_end(ap); + consoleSelect(&main_console); } /*! add text to the console @@ -350,349 +55,21 @@ console_set_status(const char *fmt, ...) void console_print(const char *fmt, ...) { - int rc; va_list ap; - /* append to the end of the console buffer */ va_start(ap, fmt); - rc = vsnprintf(end, buffer_end - end - 1, fmt, ap); + vprintf(fmt, ap); + vfprintf(stderr, fmt, ap); va_end(ap); - - /* null terminate buffer */ - end += rc; - if(end >= buffer_end) - end = buffer_end - 1; - *end = 0; - - /* scroll */ - reduce_lines(); -} - -/*! compare render information - * - * @param[in] p1 left side of comparison (render_info_t**) - * @param[in] p2 right side of comparison (render_info_t**) - * - * @returns <0 if p1 < p2 - * @returns 0 if p1 == p2 - * @returns >0 if p1 > p2 - */ -static int -render_info_cmp(const void *p1, - const void *p2) -{ - /* interpret parameters */ - render_info_t *r1 = *(render_info_t**)p1; - render_info_t *r2 = *(render_info_t**)p2; - - /* ordered by character */ - if(r1->c < r2->c) - return -1; - else if(r1->c > r2->c) - return 1; - return 0; -} - -/*! search for render info by character - * - * @param[in] font font info - * @param[in] char character - * - * @returns matching render info - */ -static render_info_t* -find_render_info(font_t *font, - char c) -{ - /* create a key to search for */ - render_info_t key, *keyptr; - key.c = c; - keyptr = &key; - - /* search for the key */ - void *info = bsearch(&keyptr, font->render_info, font->num_render_info, - sizeof(render_info_t*), render_info_cmp); - if(info == NULL) - return NULL; - - /* found it */ - return *(render_info_t**)info; -} - -/*! compare kerning information - * - * @param[in] p1 left side of comparison (kerning_info_t*) - * @param[in] p2 right side of comparison (kerning_info_t*) - * - * @returns <0 if p1 < p2 - * @returns 0 if p1 == p2 - * @returns >0 if p1 > p2 - */ -static int -kerning_info_cmp(const void *p1, - const void *p2) -{ - /* interpret parameters */ - kerning_info_t *k1 = (kerning_info_t*)p1; - kerning_info_t *k2 = (kerning_info_t*)p2; - - /* major key is prev */ - if(k1->prev < k2->prev) - return -1; - if(k1->prev > k2->prev) - return 1; - - /* minor key is next */ - if(k1->next < k2->next) - return -1; - if(k1->next > k2->next) - return 1; - - return 0; -} - -/*! search for kerning info by character pair - * - * @param[in] font font info - * @param[in] prev prev character - * @param[in] next next character - * - * @returns matching render info - */ -static kerning_info_t* -find_kerning_info(font_t *font, - char prev, - char next) -{ - /* create a key to search for */ - kerning_info_t key; - key.prev = prev; - key.next = next; - - /* search for the key */ - void *info = bsearch(&key, font->kerning_info, font->num_kerning_info, - sizeof(kerning_info_t), kerning_info_cmp); - if(info == NULL) - return NULL; - - /* found it */ - return (kerning_info_t*)info; -} - -/*! clear framebuffer - * - * @param[in] screen screen to clear - * @param[in] side which side on the stereoscopic display - * @param[in] rgbColor clear color - */ -static void -clear_screen(gfxScreen_t screen, - gfx3dSide_t side, - u8 rgbColor[3]) -{ - /* get the framebuffer information */ - u16 fbWidth, fbHeight; - u8 *fb = gfxGetFramebuffer(screen, side, &fbWidth, &fbHeight); - - /* fill the framebuffer with the clear color */ - int i; - for(i = 0; i < fbWidth*fbHeight; ++i) - { - *(fb++) = rgbColor[2]; - *(fb++) = rgbColor[1]; - *(fb++) = rgbColor[0]; - } -} - -/*! draw a quad - * - * @param[in] screen screen to draw to - * @param[in] side which side on the stereoscopic display - * @param[in] data quad data - * @param[in] x quad x position - * @param[in] y quad y position - * @param[in] w quad width - * @param[in] h quad height - * - * @note this quad data is 8-bit alpha-only - * @note uses framebuffer native coordinates - */ -static void -draw_quad(gfxScreen_t screen, - gfx3dSide_t side, - const u8 *data, - int x, - int y, - int w, - int h) -{ - int i, j; - int index = 0; - int stride = w; - - /* get the framebuffer information */ - u16 width, height; - u8 *fb = gfxGetFramebuffer(screen, side, &width, &height); - - /* this quad is totally offscreen; don't draw */ - if(x > width || y > height) - return; - - /* this quad is totally offscreen; don't draw */ - if(x + w < 0 || y + h < 0) - return; - - /* adjust parameters for partially visible quad */ - if(x < 0) - { - index -= x; - w += x; - x = 0; - } - - /* adjust parameters for partially visible quad */ - if(y < 0) - { - index -= y*stride; - h += y; - y = 0; - } - - /* adjust parameters for partially visible quad */ - if(x + w > width) - w = width - x; - - /* adjust parameters for partially visible quad */ - if(y + h > height) - h = height - y; - - /* move framebuffer pointer to quad start position */ - fb += (y*width + x)*3; - - /* fill in data */ - for(j = 0; j < h; ++j) - { - for(i = 0; i < w; ++i) - { - /* alpha blending; assuming color is white */ - int v = data[index]; - fb[0] = fb[0]*(0xFF-v)/0xFF + v; - fb[1] = fb[1]*(0xFF-v)/0xFF + v; - fb[2] = fb[2]*(0xFF-v)/0xFF + v; - - ++index; - fb += 3; - } - - index += (stride-w); - fb += (width-w)*3; - } -} - -/*! draw text to framebuffer - * - * @param[in] screen screen to draw to - * @param[in] side which side on the stereoscopic display - * @param[in] font font to use when rendering - * @param[in] data quad data - * @param[in] x quad x position - * @param[in] y quad y position - * - * @note uses intuitive coordinates - */ -static void -draw_text(gfxScreen_t screen, - gfx3dSide_t side, - font_t *font, - const char *data, - int x, - int y) -{ - render_info_t *rinfo; - kerning_info_t *kinfo; - const char *p; - int xoff = x, yoff = y; - char prev = 0; - - /* draw each character */ - for(p = data; *p != 0; ++p) - { - /* newline; move down a line and all the way left */ - if(*p == '\n') - { - xoff = x; - yoff += font->pt + font->pt/2; - prev = 0; - continue; - } - - /* look up the render info for this character */ - rinfo = find_render_info(font, *p); - - /* couldn't find it; just ignore it */ - if(rinfo == NULL) - continue; - - /* find kerning data */ - kinfo = NULL; - if(prev != 0) - kinfo = find_kerning_info(font, prev, *p); - - /* adjust for kerning */ - if(kinfo != NULL) - xoff += kinfo->x_off >> 6; - - /* save this character for next kerning lookup */ - prev = *p; - - /* render character */ - if(rinfo->width != 0 && rinfo->height != 0) - { - int x, y; - - /* get framebuffer info */ - u16 width, height; - gfxGetFramebuffer(screen, side, &width, &height); - - /* transform intuitive coordinates to framebuffer-native */ - x = width - yoff - font->pt - 2 - (rinfo->height - rinfo->y_off); - y = xoff; - - /* draw character */ - draw_quad(screen, side, rinfo->data, x, y, - rinfo->height, rinfo->width); - } - - /* advance to next character coordinate */ - xoff += rinfo->x_adv >> 6; - } } /*! draw console to screen */ void console_render(void) { - font_t *font; - /* clear all screens */ - u8 bluish[] = { 0, 0, 127 }; - clear_screen(GFX_TOP, GFX_LEFT, bluish); gfxDrawSprite(GFX_BOTTOM, GFX_LEFT, (u8*)banner_bin, 240, 320, 0, 0); - /* look up font for status bar and draw status bar */ - font = find_font("sans", 10); - if(font != NULL) - draw_text(GFX_TOP, GFX_LEFT, font, status, 4, 4); - else - debug("%s: couldn't find 'sans 10pt'\n", __func__); - - /* look up font for console and draw console */ - font = find_font("sans", 8); - if(font != NULL) - draw_text(GFX_TOP, GFX_LEFT, font, buffer, 4, 20); - else - debug("%s: couldn't find 'sans 8pt'\n", __func__); - /* flush framebuffer */ gfxFlushBuffers(); gspWaitForVBlank(); @@ -707,11 +84,6 @@ console_init(void) { } -void -console_exit(void) -{ -} - void console_set_status(const char *fmt, ...) { diff --git a/source/ftp.c b/source/ftp.c index b889e3f..bbb3170 100644 --- a/source/ftp.c +++ b/source/ftp.c @@ -1,29 +1,25 @@ #include "ftp.h" #include #include +#include #include #include #include #include #include #include +#include #include #include -#include #include +#include #include #ifdef _3DS #include <3ds.h> -#else -#include -#include +#define lstat stat #endif #include "console.h" -#ifndef _3DS -#define Errno() errno -#define closesocket(x) close(x) -#endif #define POLL_UNKNOWN (~(POLLIN|POLLOUT)) #define XFER_BUFFERSIZE 4096 @@ -51,6 +47,7 @@ FTP_DECLARE(MKD); FTP_DECLARE(MODE); FTP_DECLARE(NLST); FTP_DECLARE(NOOP); +FTP_DECLARE(OPTS); FTP_DECLARE(PASS); FTP_DECLARE(PASV); FTP_DECLARE(PORT); @@ -108,15 +105,11 @@ struct ftp_session_t size_t buffersize; /*! persistent buffer size between callbacks */ uint64_t filepos; /*! persistent file position between callbacks */ uint64_t filesize; /*! persistent file size between callbacks */ -#ifdef _3DS - Handle fd; /*! persistent handle between callbacks */ -#else union { DIR *dp; /*! persistent open directory pointer between callbacks */ int fd; /*! persistent open file descriptor between callbacks */ }; -#endif }; /*! ftp command descriptor */ @@ -141,6 +134,7 @@ static ftp_command_t ftp_commands[] = FTP_COMMAND(MODE), FTP_COMMAND(NLST), FTP_COMMAND(NOOP), + FTP_COMMAND(OPTS), FTP_COMMAND(PASS), FTP_COMMAND(PASV), FTP_COMMAND(PORT), @@ -165,13 +159,6 @@ static ftp_command_t ftp_commands[] = /*! number of ftp commands */ static const size_t num_ftp_commands = sizeof(ftp_commands)/sizeof(ftp_commands[0]); -static inline int Errno(void) -{ - if(errno < 0) - return -errno; - return errno; -} - /*! compare ftp command descriptors * * @param[in] p1 left side of comparison (ftp_command_t*) @@ -195,34 +182,6 @@ ftp_command_cmp(const void *p1, #ifdef _3DS /*! SOC service buffer */ 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 /*! server listen address */ @@ -230,9 +189,9 @@ static struct sockaddr_in serv_addr; /*! listen file descriptor */ static int listenfd = -1; /*! current data port */ -in_port_t data_port = DATA_PORT; +static in_port_t data_port = DATA_PORT; /*! list of ftp sessions */ -ftp_session_t *sessions = NULL; +static ftp_session_t *sessions = NULL; /*! Allocate a new data port * @@ -264,14 +223,14 @@ ftp_set_socket_nonblocking(int fd) flags = fcntl(fd, F_GETFL, 0); if(flags == -1) { - console_print("fcntl: %d %s\n", Errno(), strerror(Errno())); + console_print(RED "fcntl: %d %s\n" RESET, errno, strerror(errno)); return -1; } rc = fcntl(fd, F_SETFL, flags | O_NONBLOCK); if(rc != 0) { - console_print("fcntl: %d %s\n", Errno(), strerror(Errno())); + console_print(RED "fcntl: %d %s\n" RESET, errno, strerror(errno)); return -1; } @@ -296,23 +255,23 @@ ftp_closesocket(int fd, int connected) rc = getpeername(fd, (struct sockaddr*)&addr, &addrlen); if(rc != 0) { - console_print("getpeername: %d %s\n", Errno(), strerror(Errno())); - console_print("closing connection to fd=%d\n", fd); + console_print(RED "getpeername: %d %s\n" RESET, errno, strerror(errno)); + console_print(YELLOW "closing connection to fd=%d\n" RESET, fd); } else - console_print("closing connection to %s:%u\n", + console_print(YELLOW "closing connection to %s:%u\n" RESET, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); /* shutdown connection */ rc = shutdown(fd, SHUT_RDWR); if(rc != 0) - console_print("shutdown: %d %s\n", Errno(), strerror(Errno())); + console_print(RED "shutdown: %d %s\n" RESET, errno, strerror(errno)); } /* close socket */ - rc = closesocket(fd); + rc = close(fd); if(rc != 0) - console_print("closesocket: %d %s\n", Errno(), strerror(Errno())); + console_print(RED "close: %d %s\n" RESET, errno, strerror(errno)); } /*! close command socket on ftp session @@ -334,7 +293,7 @@ ftp_session_close_cmd(ftp_session_t *session) static void ftp_session_close_pasv(ftp_session_t *session) { - console_print("stop listening on %s:%u\n", + console_print(YELLOW "stop listening on %s:%u\n" RESET, inet_ntoa(session->pasv_addr.sin_addr), ntohs(session->pasv_addr.sin_port)); @@ -364,21 +323,12 @@ ftp_session_close_data(ftp_session_t *session) static void ftp_session_close_file(ftp_session_t *session) { -#ifdef _3DS - Result ret; - - ret = FSFILE_Close(session->fd); - if(ret != 0) - console_print("FSFILE_Close: 0x%08X\n", (unsigned int)ret); - session->fd = -1; -#else int rc; rc = close(session->fd); if(rc != 0) - console_print("close: %d %s\n", errno, strerror(errno)); + console_print(RED "close: %d %s\n" RESET, errno, strerror(errno)); session->fd = -1; -#endif } /*! open file for reading for ftp session @@ -390,30 +340,6 @@ ftp_session_close_file(ftp_session_t *session) static int 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("FSUSER_OpenFile: 0x%08X\n", (unsigned int)ret); - return -1; - } - - /* get the file size */ - ret = FSFILE_GetSize(session->fd, &size); - if(ret != 0) - { - console_print("FSFILE_GetSize: 0x%08X\n", (unsigned int)ret); - ftp_session_close_file(session); - return -1; - } - session->filesize = size; -#else int rc; struct stat st; @@ -421,7 +347,7 @@ ftp_session_open_file_read(ftp_session_t *session) session->fd = open(session->buffer, O_RDONLY); if(session->fd < 0) { - console_print("open '%s': %d %s\n", session->buffer, errno, strerror(errno)); + console_print(RED "open '%s': %d %s\n" RESET, session->buffer, errno, strerror(errno)); return -1; } @@ -429,12 +355,11 @@ ftp_session_open_file_read(ftp_session_t *session) rc = fstat(session->fd, &st); if(rc != 0) { - console_print("fstat '%s': %d %s\n", session->buffer, errno, strerror(errno)); + console_print(RED "fstat '%s': %d %s\n" RESET, session->buffer, errno, strerror(errno)); ftp_session_close_file(session); return -1; } session->filesize = st.st_size; -#endif /* reset file position */ /* TODO: support REST command */ @@ -452,32 +377,13 @@ ftp_session_open_file_read(ftp_session_t *session) static ssize_t 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("FSFILE_Read: 0x%08X\n", (unsigned int)ret); - return -1; - } - - /* adjust file position */ - session->filepos += bytes; - - return bytes; -#else ssize_t rc; /* read file at current position */ - /* TODO: maybe use pread? */ rc = read(session->fd, session->buffer, sizeof(session->buffer)); if(rc < 0) { - console_print("read: %d %s\n", errno, strerror(errno)); + console_print(RED "read: %d %s\n" RESET, errno, strerror(errno)); return -1; } @@ -485,7 +391,6 @@ ftp_session_read_file(ftp_session_t *session) session->filepos += rc; return rc; -#endif } /*! open file for writing for ftp session @@ -499,35 +404,13 @@ ftp_session_read_file(ftp_session_t *session) static int 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("FSUSER_OpenFile: 0x%08X\n", (unsigned int)ret); - return -1; - } - - /* truncate file */ - ret = FSFILE_SetSize(session->fd, 0); - if(ret != 0) - { - console_print("FSFILE_SetSize: 0x%08X\n", (unsigned int)ret); - ftp_session_close_file(session); - } -#else /* open file in write and create mode with truncation */ session->fd = open(session->buffer, O_WRONLY|O_CREAT|O_TRUNC, 0644); if(session->fd < 0) { - console_print("open '%s': %d %s\n", session->buffer, errno, strerror(errno)); + console_print(RED "open '%s': %d %s\n" RESET, session->buffer, errno, strerror(errno)); return -1; } -#endif /* reset file position */ /* TODO: support REST command */ @@ -545,47 +428,23 @@ ftp_session_open_file_write(ftp_session_t *session) static ssize_t 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("FSFILE_Write: 0x%08X\n", (unsigned int)ret); - return -1; - } - else if(bytes == 0) - console_print("FSFILE_Write: wrote 0 bytes\n"); - - /* adjust file position */ - session->filepos += bytes; - - return bytes; -#else ssize_t rc; /* write to file at current position */ - /* TODO: maybe use writev? */ rc = write(session->fd, session->buffer + session->bufferpos, session->buffersize - session->bufferpos); if(rc < 0) { - console_print("write: %d %s\n", errno, strerror(errno)); + console_print(RED "write: %d %s\n" RESET, errno, strerror(errno)); return -1; } else if(rc == 0) - console_print("write: wrote 0 bytes\n"); + console_print(RED "write: wrote 0 bytes\n" RESET); /* adjust file position */ session->filepos += rc; return rc; -#endif } /*! close current working directory for ftp session @@ -595,23 +454,13 @@ ftp_session_write_file(ftp_session_t *session) static void 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("FSDIR_Close: 0x%08X\n", (unsigned int)ret); - session->fd = -1; -#else int rc; /* close open directory pointer */ rc = closedir(session->dp); if(rc != 0) - console_print("closedir: %d %s\n", errno, strerror(errno)); + console_print(RED "closedir: %d %s\n" RESET, errno, strerror(errno)); session->dp = NULL; -#endif } /*! open current working directory for ftp session @@ -623,26 +472,13 @@ ftp_session_close_cwd(ftp_session_t *session) static int 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("FSUSER_OpenDirectory: 0x%08X\n", (unsigned int)ret); - return -1; - } -#else /* open current working directory */ session->dp = opendir(session->cwd); if(session->dp == NULL) { - console_print("opendir '%s': %d %s\n", session->cwd, errno, strerror(errno)); + console_print(RED "opendir '%s': %d %s\n" RESET, session->cwd, errno, strerror(errno)); return -1; } -#endif return 0; } @@ -712,25 +548,28 @@ ftp_send_response(ftp_session_t *session, /* print response code and message to buffer */ va_start(ap, fmt); - rc = sprintf(buffer, "%d ", code); + if(code != 211) + rc = sprintf(buffer, "%d ", code); + else + rc = sprintf(buffer, "%d- ", code); rc += vsnprintf(buffer+rc, sizeof(buffer)-rc, fmt, ap); va_end(ap); if(rc >= sizeof(buffer)) { /* couldn't fit message; just send code */ - console_print("%s: buffersize too small\n", __func__); + console_print(RED "%s: buffersize too small\n" RESET, __func__); rc = sprintf(buffer, "%d\r\n", code); } /* send response */ to_send = rc; - console_print("%s", buffer); + console_print(GREEN "%s" RESET, buffer); rc = send(session->cmd_fd, buffer, to_send, 0); if(rc < 0) - console_print("send: %d %s\n", Errno(), strerror(Errno())); + console_print(RED "send: %d %s\n" RESET, errno, strerror(errno)); else if(rc != to_send) - console_print("only sent %u/%u bytes\n", + console_print(RED "only sent %u/%u bytes\n" RESET, (unsigned int)rc, (unsigned int)to_send); return rc; @@ -739,8 +578,6 @@ ftp_send_response(ftp_session_t *session, /*! destroy ftp session * * @param[in] session ftp session - * - * @returns next session in list */ static ftp_session_t* ftp_session_destroy(ftp_session_t *session) @@ -790,18 +627,18 @@ ftp_session_new(int listen_fd) new_fd = accept(listen_fd, (struct sockaddr*)&addr, &addrlen); if(new_fd < 0) { - console_print("accept: %d %s\n", Errno(), strerror(Errno())); + console_print(RED "accept: %d %s\n" RESET, errno, strerror(errno)); return; } - console_print("accepted connection from %s:%u\n", + console_print(CYAN "accepted connection from %s:%u\n" RESET, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); /* allocate a new session */ session = (ftp_session_t*)malloc(sizeof(ftp_session_t)); if(session == NULL) { - console_print("failed to allocate session\n"); + console_print(RED "failed to allocate session\n" RESET); ftp_closesocket(new_fd, 1); return; } @@ -837,7 +674,7 @@ ftp_session_new(int listen_fd) rc = getsockname(new_fd, (struct sockaddr*)&session->pasv_addr, &addrlen); if(rc != 0) { - console_print("getsockname: %d %s\n", 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_session_destroy(session); return; @@ -876,7 +713,7 @@ ftp_session_accept(ftp_session_t *session) new_fd = accept(session->pasv_fd, (struct sockaddr*)&addr, &addrlen); if(new_fd < 0) { - console_print("accept: %d %s\n", Errno(), strerror(Errno())); + console_print(RED "accept: %d %s\n" RESET, errno, strerror(errno)); ftp_session_set_state(session, COMMAND_STATE); ftp_send_response(session, 425, "Failed to establish connection\r\n"); return -1; @@ -891,7 +728,7 @@ ftp_session_accept(ftp_session_t *session) return -1; } - console_print("accepted connection from %s:%u\n", + console_print(CYAN "accepted connection from %s:%u\n" RESET, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); ftp_session_set_state(session, DATA_TRANSFER_STATE); @@ -925,7 +762,7 @@ ftp_session_connect(ftp_session_t *session) session->data_fd = socket(AF_INET, SOCK_STREAM, 0); if(session->data_fd < 0) { - console_print("socket: %d %s\n", Errno(), strerror(Errno())); + console_print(RED "socket: %d %s\n" RESET, errno, strerror(errno)); return -1; } @@ -934,7 +771,7 @@ ftp_session_connect(ftp_session_t *session) sizeof(session->peer_addr)); if(rc != 0) { - console_print("connect: %d %s\n", Errno(), strerror(Errno())); + console_print(RED "connect: %d %s\n" RESET, errno, strerror(errno)); ftp_closesocket(session->data_fd, 0); session->data_fd = -1; return -1; @@ -944,7 +781,7 @@ ftp_session_connect(ftp_session_t *session) if(rc != 0) return -1; - console_print("connected to %s:%u\n", + console_print(CYAN "connected to %s:%u\n" RESET, inet_ntoa(session->peer_addr.sin_addr), ntohs(session->peer_addr.sin_port)); @@ -970,7 +807,7 @@ ftp_session_read_command(ftp_session_t *session) if(rc < 0) { /* error retrieving command */ - console_print("recv: %d %s\n", Errno(), strerror(Errno())); + console_print(RED "recv: %d %s\n" RESET, errno, strerror(errno)); ftp_session_close_cmd(session); return; } @@ -1061,7 +898,7 @@ ftp_session_poll(ftp_session_t *session) /* poll the selected socket */ rc = poll(&pollinfo, 1, 0); if(rc < 0) - console_print("poll: %d %s\n", Errno(), strerror(Errno())); + console_print(RED "poll: %d %s\n" RESET, errno, strerror(errno)); else if(rc > 0) { if(pollinfo.revents != 0) @@ -1071,7 +908,7 @@ ftp_session_poll(ftp_session_t *session) { case COMMAND_STATE: if(pollinfo.revents & POLL_UNKNOWN) - console_print("cmd_fd: revents=0x%08X\n", pollinfo.revents); + console_print(YELLOW "cmd_fd: revents=0x%08X\n" RESET, pollinfo.revents); /* we need to read a new command */ if(pollinfo.revents & (POLLERR|POLLHUP)) @@ -1082,7 +919,7 @@ ftp_session_poll(ftp_session_t *session) case DATA_CONNECT_STATE: if(pollinfo.revents & POLL_UNKNOWN) - console_print("pasv_fd: revents=0x%08X\n", pollinfo.revents); + console_print(YELLOW "pasv_fd: revents=0x%08X\n" RESET, pollinfo.revents); /* we need to accept the PASV connection */ if(pollinfo.revents & (POLLERR|POLLHUP)) @@ -1099,7 +936,7 @@ ftp_session_poll(ftp_session_t *session) case DATA_TRANSFER_STATE: if(pollinfo.revents & POLL_UNKNOWN) - console_print("data_fd: revents=0x%08X\n", pollinfo.revents); + console_print(YELLOW "data_fd: revents=0x%08X\n" RESET, pollinfo.revents); /* we need to transfer data */ if(pollinfo.revents & (POLLERR|POLLHUP)) @@ -1135,48 +972,49 @@ ftp_init(void) ret = fsInit(); if(ret != 0) { - console_print("fsInit: 0x%08X\n", (unsigned int)ret); - return -1; + console_print(RED "fsInit: 0x%08X\n" RESET, (unsigned int)ret); + goto fs_fail; } - /* open SDMC archive */ - ret = FSUSER_OpenArchive(NULL, &sdmcArchive); + /* initialize sdmc_dev */ + ret = sdmcInit(); if(ret != 0) { - console_print("FSUSER_OpenArchive: 0x%08X\n", (unsigned int)ret); - ret = fsExit(); - if(ret != 0) - console_print("fsExit: 0x%08X\n", (unsigned int)ret); - return -1; + console_print(RED "sdmcInit: 0x%08X\n" RESET, (unsigned int)ret); + goto sdmc_fail; } +#if ENABLE_LOGGING + /* open log file */ + FILE *fp = freopen("/ftbrony.log", "wb", stderr); + if(fp == NULL) + { + console_print(RED "freopen: 0x%08X\n" RESET, errno); + goto stderr_fail; + } + + /* truncate log file */ + if(ftruncate(fileno(fp), 0) != 0) + { + console_print(RED "ftruncate: 0x%08X\n" RESET, errno); + goto ftruncate_fail; + } +#endif + /* allocate buffer for SOC service */ SOC_buffer = (u32*)memalign(SOC_ALIGN, SOC_BUFFERSIZE); if(SOC_buffer == NULL) { - console_print("memalign: failed to allocate\n"); - ret = FSUSER_CloseArchive(NULL, &sdmcArchive); - if(ret != 0) - console_print("FSUSER_CloseArchive: 0x%08X\n", (unsigned int)ret); - ret = fsExit(); - if(ret != 0) - console_print("fsExit: 0x%08X\n", (unsigned int)ret); - return -1; + console_print(RED "memalign: failed to allocate\n" RESET); + goto memalign_fail; } /* initialize SOC service */ ret = SOC_Initialize(SOC_buffer, SOC_BUFFERSIZE); if(ret != 0) { - console_print("SOC_Initialize: 0x%08X\n", (unsigned int)ret); - free(SOC_buffer); - ret = FSUSER_CloseArchive(NULL, &sdmcArchive); - if(ret != 0) - console_print("FSUSER_CloseArchive: 0x%08X\n", (unsigned int)ret); - ret = fsExit(); - if(ret != 0) - console_print("fsExit: 0x%08X\n", (unsigned int)ret); - return -1; + console_print(RED "SOC_Initialize: 0x%08X\n" RESET, (unsigned int)ret); + goto soc_fail; } #endif @@ -1184,7 +1022,7 @@ ftp_init(void) listenfd = socket(AF_INET, SOCK_STREAM, 0); if(listenfd < 0) { - console_print("socket: %d %s\n", Errno(), strerror(Errno())); + console_print(RED "socket: %d %s\n" RESET, errno, strerror(errno)); ftp_exit(); return -1; } @@ -1204,7 +1042,7 @@ ftp_init(void) rc = setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)); if(rc != 0) { - console_print("setsockopt: %d %s\n", Errno(), strerror(Errno())); + console_print(RED "setsockopt: %d %s\n" RESET, errno, strerror(errno)); ftp_exit(); return -1; } @@ -1215,7 +1053,7 @@ ftp_init(void) rc = bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); if(rc != 0) { - console_print("bind: %d %s\n", Errno(), strerror(Errno())); + console_print(RED "bind: %d %s\n" RESET, errno, strerror(errno)); ftp_exit(); return -1; } @@ -1224,14 +1062,17 @@ ftp_init(void) rc = listen(listenfd, 5); if(rc != 0) { - console_print("listen: %d %s\n", Errno(), strerror(Errno())); + console_print(RED "listen: %d %s\n" RESET, errno, strerror(errno)); ftp_exit(); return -1; } /* print server address */ #ifdef _3DS - console_set_status(STATUS_STRING " IP:%s Port:%u", + console_set_status("\n" GREEN STATUS_STRING " " + YELLOW "IP:" CYAN "%s " + YELLOW "Port:" CYAN "%u" + RESET, inet_ntoa(serv_addr.sin_addr), ntohs(serv_addr.sin_port)); #else @@ -1241,7 +1082,7 @@ ftp_init(void) rc = getsockname(listenfd, (struct sockaddr*)&serv_addr, &addrlen); if(rc != 0) { - console_print("getsockname: %d %s\n", Errno(), strerror(Errno())); + console_print(RED "getsockname: %d %s\n" RESET, errno, strerror(errno)); ftp_exit(); return -1; } @@ -1249,18 +1090,46 @@ ftp_init(void) rc = gethostname(hostname, sizeof(hostname)); if(rc != 0) { - console_print("gethostname: %d %s\n", Errno(), strerror(Errno())); + console_print(RED "gethostname: %d %s\n" RESET, errno, strerror(errno)); ftp_exit(); return -1; } - console_set_status(STATUS_STRING " IP:%s Port:%u", + console_set_status(GREEN STATUS_STRING " " + YELLOW "IP:" CYAN "%s " + YELLOW "Port:" CYAN "%u" + RESET, hostname, ntohs(serv_addr.sin_port)); } #endif return 0; + +#ifdef _3DS +soc_fail: + free(SOC_buffer); + +memalign_fail: +#ifdef ENABLE_LOGGING +ftruncate_fail: + if(fclose(stderr) != 0) + console_print(RED "fclose: 0x%08X\n" RESET, errno); + +stderr_fail: +#endif + ret = sdmcExit(); + if(ret != 0) + console_print(RED "sdmcExit: 0x%08X\n" RESET, (unsigned int)ret); + +sdmc_fail: + ret = fsExit(); + if(ret != 0) + console_print(RED "fsExit: 0x%08X\n" RESET, (unsigned int)ret); + +fs_fail: + return -1; +#endif } /*! deinitialize ftp subsystem */ @@ -1283,13 +1152,24 @@ ftp_exit(void) /* deinitialize SOC service */ ret = SOC_Shutdown(); if(ret != 0) - console_print("SOC_Shutdown: 0x%08X\n", (unsigned int)ret); + console_print(RED "SOC_Shutdown: 0x%08X\n" RESET, (unsigned int)ret); free(SOC_buffer); +#ifdef ENABLE_LOGGING + /* close log file */ + if(fclose(stderr) != 0) + console_print(RED "fclose: 0x%08X\n" RESET, errno); + + /* deinitialize sdmc_dev */ + ret = sdmcExit(); + if(ret != 0) + console_print(RED "sdmcExit: 0x%08X\n" RESET, (unsigned int)ret); +#endif + /* deinitialize FS service */ ret = fsExit(); if(ret != 0) - console_print("fsExit: 0x%08X\n", (unsigned int)ret); + console_print(RED "fsExit: 0x%08X\n" RESET, (unsigned int)ret); #endif } @@ -1306,7 +1186,10 @@ ftp_loop(void) rc = poll(&pollinfo, 1, 0); if(rc < 0) - console_print("poll: %d %s\n", Errno(), strerror(Errno())); + { + console_print(RED "poll: %d %s\n" RESET, errno, strerror(errno)); + return -1; + } else if(rc > 0) { if(pollinfo.revents & POLLIN) @@ -1315,7 +1198,7 @@ ftp_loop(void) } else { - console_print("listenfd: revents=0x%08X\n", pollinfo.revents); + console_print(YELLOW "listenfd: revents=0x%08X\n" RESET, pollinfo.revents); } } @@ -1420,47 +1303,10 @@ build_path(ftp_session_t *session, static int list_transfer(ftp_session_t *session) { -#ifdef _3DS - Result ret; -#endif ssize_t rc; 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("FSDIR_Read: 0x%08X\n", (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 dirent *dent = readdir(session->dp); if(dent == NULL) @@ -1474,12 +1320,16 @@ list_transfer(ftp_session_t *session) if(strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0) return 0; - snprintf(session->buffer, sizeof(session->buffer), - "%s/%s", session->cwd, dent->d_name); + if(strcmp(session->cwd, "/") == 0) + snprintf(session->buffer, sizeof(session->buffer), + "/%s", dent->d_name); + else + snprintf(session->buffer, sizeof(session->buffer), + "%s/%s", session->cwd, dent->d_name); rc = lstat(session->buffer, &st); if(rc != 0) { - console_print("stat '%s': %d %s\n", session->buffer, errno, strerror(errno)); + console_print(RED "stat '%s': %d %s\n" RESET, session->buffer, errno, strerror(errno)); ftp_session_close_cwd(session); ftp_session_set_state(session, COMMAND_STATE); ftp_send_response(session, 550, "unavailable\r\n"); @@ -1493,7 +1343,6 @@ list_transfer(ftp_session_t *session) S_ISLNK(st.st_mode) ? 'l' : '-', (unsigned long long)st.st_size, dent->d_name); -#endif session->bufferpos = 0; } @@ -1503,12 +1352,12 @@ list_transfer(ftp_session_t *session) { if(rc < 0) { - if(Errno() == EWOULDBLOCK) + if(errno == EWOULDBLOCK) return -1; - console_print("send: %d %s\n", Errno(), strerror(Errno())); + console_print(RED "send: %d %s\n" RESET, errno, strerror(errno)); } else - console_print("send: %d %s\n", ECONNRESET, strerror(ECONNRESET)); + console_print(YELLOW "send: %d %s\n" RESET, ECONNRESET, strerror(ECONNRESET)); ftp_session_close_cwd(session); ftp_session_set_state(session, COMMAND_STATE); @@ -1549,12 +1398,12 @@ retrieve_transfer(ftp_session_t *session) { if(rc < 0) { - if(Errno() == EWOULDBLOCK) + if(errno == EWOULDBLOCK) return -1; - console_print("send: %d %s\n", Errno(), strerror(Errno())); + console_print(RED "send: %d %s\n" RESET, errno, strerror(errno)); } else - console_print("send: %d %s\n", ECONNRESET, strerror(ECONNRESET)); + console_print(YELLOW "send: %d %s\n" RESET, ECONNRESET, strerror(ECONNRESET)); ftp_session_close_file(session); ftp_session_set_state(session, COMMAND_STATE); @@ -1578,9 +1427,9 @@ store_transfer(ftp_session_t *session) { if(rc < 0) { - if(Errno() == EWOULDBLOCK) + if(errno == EWOULDBLOCK) return -1; - console_print("recv: %d %s\n", Errno(), strerror(Errno())); + console_print(RED "recv: %d %s\n" RESET, errno, strerror(errno)); } ftp_session_close_file(session); @@ -1588,7 +1437,6 @@ store_transfer(ftp_session_t *session) if(rc == 0) { - console_print("Wrote %llu bytes\n", session->filepos); ftp_send_response(session, 226, "OK\r\n"); } else @@ -1621,7 +1469,7 @@ store_transfer(ftp_session_t *session) FTP_DECLARE(ALLO) { - console_print("%s %s\n", __func__, args ? args : ""); + console_print(CYAN "%s %s\n" RESET, __func__, args ? args : ""); ftp_session_set_state(session, COMMAND_STATE); @@ -1631,7 +1479,7 @@ FTP_DECLARE(ALLO) FTP_DECLARE(APPE) { /* TODO */ - console_print("%s %s\n", __func__, args ? args : ""); + console_print(CYAN "%s %s\n" RESET, __func__, args ? args : ""); ftp_session_set_state(session, COMMAND_STATE); @@ -1640,7 +1488,7 @@ FTP_DECLARE(APPE) FTP_DECLARE(CDUP) { - console_print("%s %s\n", __func__, args ? args : ""); + console_print(CYAN "%s %s\n" RESET, __func__, args ? args : ""); ftp_session_set_state(session, COMMAND_STATE); @@ -1651,7 +1499,7 @@ FTP_DECLARE(CDUP) FTP_DECLARE(CWD) { - console_print("%s %s\n", __func__, args ? args : ""); + console_print(CYAN "%s %s\n" RESET, __func__, args ? args : ""); ftp_session_set_state(session, COMMAND_STATE); @@ -1665,32 +1513,18 @@ FTP_DECLARE(CWD) 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("FSDIR_Close: 0x%08X\n", (unsigned int)ret); -#else struct stat st; int rc; rc = stat(session->buffer, &st); if(rc != 0) { - console_print("stat '%s': %d %s\n", session->buffer, errno, strerror(errno)); + console_print(RED "stat '%s': %d %s\n" RESET, session->buffer, errno, strerror(errno)); return ftp_send_response(session, 550, "unavailable\r\n"); } if(!S_ISDIR(st.st_mode)) return ftp_send_response(session, 553, "not a directory\r\n"); -#endif } strncpy(session->cwd, session->buffer, sizeof(session->cwd)); @@ -1700,52 +1534,39 @@ FTP_DECLARE(CWD) FTP_DECLARE(DELE) { -#ifdef _3DS - Result ret; -#else - int rc; -#endif + int rc; - console_print("%s %s\n", __func__, args ? args : ""); + console_print(CYAN "%s %s\n" RESET, __func__, args ? args : ""); ftp_session_set_state(session, COMMAND_STATE); if(build_path(session, args) != 0) 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("FSUSER_DeleteFile: 0x%08X\n", (unsigned int)ret); - return ftp_send_response(session, 550, "failed to delete file\r\n"); - } -#else rc = unlink(session->buffer); if(rc != 0) { - console_print("unlink: %d %s\n", 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"); } -#endif return ftp_send_response(session, 250, "OK\r\n"); } FTP_DECLARE(FEAT) { - console_print("%s %s\n", __func__, args ? args : ""); + console_print(CYAN "%s %s\n" RESET, __func__, args ? args : ""); 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) { ssize_t rc; - console_print("%s %s\n", __func__, args ? args : ""); + console_print(CYAN "%s %s\n" RESET, __func__, args ? args : ""); if(ftp_session_open_cwd(session) != 0) { @@ -1791,41 +1612,28 @@ FTP_DECLARE(LIST) FTP_DECLARE(MKD) { -#ifdef _3DS - Result ret; -#else - int rc; -#endif + int rc; - console_print("%s %s\n", __func__, args ? args : ""); + console_print(CYAN "%s %s\n" RESET, __func__, args ? args : ""); ftp_session_set_state(session, COMMAND_STATE); if(build_path(session, args) != 0) 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("FSUSER_OpenDirectory: 0x%08X\n", (unsigned int)ret); - return ftp_send_response(session, 550, "failed to create directory\r\n"); - } -#else rc = mkdir(session->buffer, 0755); if(rc != 0) { - console_print("mkdir: %d %s\n", 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"); } -#endif return ftp_send_response(session, 250, "OK\r\n"); } FTP_DECLARE(MODE) { - console_print("%s %s\n", __func__, args ? args : ""); + console_print(CYAN "%s %s\n" RESET, __func__, args ? args : ""); ftp_session_set_state(session, COMMAND_STATE); @@ -1838,7 +1646,7 @@ FTP_DECLARE(MODE) FTP_DECLARE(NLST) { /* TODO */ - console_print("%s %s\n", __func__, args ? args : ""); + console_print(CYAN "%s %s\n" RESET, __func__, args ? args : ""); ftp_session_set_state(session, COMMAND_STATE); @@ -1847,13 +1655,27 @@ FTP_DECLARE(NLST) FTP_DECLARE(NOOP) { - console_print("%s %s\n", __func__, args ? args : ""); + console_print(CYAN "%s %s\n" RESET, __func__, args ? args : ""); 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) { - console_print("%s %s\n", __func__, args ? args : ""); + console_print(CYAN "%s %s\n" RESET, __func__, args ? args : ""); ftp_session_set_state(session, COMMAND_STATE); @@ -1867,7 +1689,7 @@ FTP_DECLARE(PASV) char *p; in_port_t port; - console_print("%s %s\n", __func__, args ? args : ""); + console_print(CYAN "%s %s\n" RESET, __func__, args ? args : ""); memset(buffer, 0, sizeof(buffer)); @@ -1878,14 +1700,14 @@ FTP_DECLARE(PASV) session->pasv_fd = socket(AF_INET, SOCK_STREAM, 0); if(session->pasv_fd < 0) { - console_print("socket: %d %s\n", Errno(), strerror(Errno())); + console_print(RED "socket: %d %s\n" RESET, errno, strerror(errno)); return ftp_send_response(session, 451, "\r\n"); } session->pasv_addr.sin_port = htons(next_data_port()); #ifdef _3DS - console_print("binding to %s:%u\n", + console_print(YELLOW "binding to %s:%u\n" RESET, inet_ntoa(session->pasv_addr.sin_addr), ntohs(session->pasv_addr.sin_port)); #endif @@ -1893,7 +1715,7 @@ FTP_DECLARE(PASV) sizeof(session->pasv_addr)); if(rc != 0) { - console_print("bind: %d %s\n", Errno(), strerror(Errno())); + console_print(RED "bind: %d %s\n" RESET, errno, strerror(errno)); ftp_session_close_pasv(session); return ftp_send_response(session, 451, "\r\n"); } @@ -1901,7 +1723,7 @@ FTP_DECLARE(PASV) rc = listen(session->pasv_fd, 5); if(rc != 0) { - console_print("listen: %d %s\n", Errno(), strerror(Errno())); + console_print(RED "listen: %d %s\n" RESET, errno, strerror(errno)); ftp_session_close_pasv(session); return ftp_send_response(session, 451, "\r\n"); } @@ -1913,14 +1735,14 @@ FTP_DECLARE(PASV) &addrlen); if(rc != 0) { - console_print("getsockname: %d %s\n", Errno(), strerror(Errno())); + console_print(RED "getsockname: %d %s\n" RESET, errno, strerror(errno)); ftp_session_close_pasv(session); return ftp_send_response(session, 451, "\r\n"); } } #endif - console_print("listening on %s:%u\n", + console_print(YELLOW "listening on %s:%u\n" RESET, inet_ntoa(session->pasv_addr.sin_addr), ntohs(session->pasv_addr.sin_port)); @@ -1947,7 +1769,7 @@ FTP_DECLARE(PORT) unsigned long val; struct sockaddr_in addr; - console_print("%s %s\n", __func__, args ? args : ""); + console_print(CYAN "%s %s\n" RESET, __func__, args ? args : ""); ftp_session_set_state(session, COMMAND_STATE); @@ -2029,7 +1851,7 @@ FTP_DECLARE(PORT) FTP_DECLARE(PWD) { - console_print("%s %s\n", __func__, args ? args : ""); + console_print(CYAN "%s %s\n" RESET, __func__, args ? args : ""); ftp_session_set_state(session, COMMAND_STATE); @@ -2038,7 +1860,7 @@ FTP_DECLARE(PWD) FTP_DECLARE(QUIT) { - console_print("%s %s\n", __func__, args ? args : ""); + console_print(CYAN "%s %s\n" RESET, __func__, args ? args : ""); ftp_send_response(session, 221, "disconnecting\r\n"); ftp_session_close_cmd(session); @@ -2049,7 +1871,7 @@ FTP_DECLARE(QUIT) FTP_DECLARE(REST) { /* TODO */ - console_print("%s %s\n", __func__, args ? args : ""); + console_print(CYAN "%s %s\n" RESET, __func__, args ? args : ""); ftp_session_set_state(session, COMMAND_STATE); @@ -2060,7 +1882,7 @@ FTP_DECLARE(RETR) { int rc; - console_print("%s %s\n", __func__, args ? args : ""); + console_print(CYAN "%s %s\n" RESET, __func__, args ? args : ""); if(build_path(session, args) != 0) { @@ -2113,83 +1935,42 @@ FTP_DECLARE(RETR) FTP_DECLARE(RMD) { -#ifdef _3DS - Result ret; -#else - int rc; -#endif + int rc; - console_print("%s %s\n", __func__, args ? args : ""); + console_print(CYAN "%s %s\n" RESET, __func__, args ? args : ""); ftp_session_set_state(session, COMMAND_STATE); if(build_path(session, args) != 0) 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("FSUSER_DeleteDirectory: 0x%08X\n", (unsigned int)ret); - return ftp_send_response(session, 550, "failed to delete directory\r\n"); - } -#else rc = rmdir(session->buffer); if(rc != 0) { - console_print("rmdir: %d %s\n", 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"); } -#endif return ftp_send_response(session, 250, "OK\r\n"); } FTP_DECLARE(RNFR) { -#ifdef _3DS - Result ret; - Handle fd; -#else int rc; struct stat st; -#endif - console_print("%s %s\n", __func__, args ? args : ""); + console_print(CYAN "%s %s\n" RESET, __func__, args ? args : ""); ftp_session_set_state(session, COMMAND_STATE); if(build_path(session, args) != 0) 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("no such file or directory\n"); - return ftp_send_response(session, 450, "no such file or directory\r\n"); - } -#else rc = lstat(session->buffer, &st); if(rc != 0) { - console_print("lstat: %d %s\n", 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"); } -#endif session->flags |= SESSION_RENAME; @@ -2198,14 +1979,10 @@ FTP_DECLARE(RNFR) FTP_DECLARE(RNTO) { -#ifdef _3DS - Result ret; -#else - int rc; -#endif + int rc; char buffer[XFER_BUFFERSIZE]; - console_print("%s %s\n", __func__, args ? args : ""); + console_print(CYAN "%s %s\n" RESET, __func__, args ? args : ""); ftp_session_set_state(session, COMMAND_STATE); @@ -2219,27 +1996,12 @@ FTP_DECLARE(RNTO) if(build_path(session, args) != 0) 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("FSUSER_RenameFile/Directory: 0x%08X\n", (unsigned int)ret); - return ftp_send_response(session, 550, "failed to rename file/directory\r\n"); - } -#else rc = rename(buffer, session->buffer); if(rc != 0) { - console_print("rename: %d %s\n", 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"); } -#endif return ftp_send_response(session, 250, "OK\r\n"); } @@ -2248,7 +2010,7 @@ FTP_DECLARE(STOR) { int rc; - console_print("%s %s\n", __func__, args ? args : ""); + console_print(CYAN "%s %s\n" RESET, __func__, args ? args : ""); if(build_path(session, args) != 0) { @@ -2301,7 +2063,7 @@ FTP_DECLARE(STOR) FTP_DECLARE(STOU) { - console_print("%s %s\n", __func__, args ? args : ""); + console_print(CYAN "%s %s\n" RESET, __func__, args ? args : ""); ftp_session_set_state(session, COMMAND_STATE); @@ -2310,7 +2072,7 @@ FTP_DECLARE(STOU) FTP_DECLARE(STRU) { - console_print("%s %s\n", __func__, args ? args : ""); + console_print(CYAN "%s %s\n" RESET, __func__, args ? args : ""); ftp_session_set_state(session, COMMAND_STATE); @@ -2322,7 +2084,7 @@ FTP_DECLARE(STRU) FTP_DECLARE(SYST) { - console_print("%s %s\n", __func__, args ? args : ""); + console_print(CYAN "%s %s\n" RESET, __func__, args ? args : ""); ftp_session_set_state(session, COMMAND_STATE); @@ -2331,7 +2093,7 @@ FTP_DECLARE(SYST) FTP_DECLARE(TYPE) { - console_print("%s %s\n", __func__, args ? args : ""); + console_print(CYAN "%s %s\n" RESET, __func__, args ? args : ""); ftp_session_set_state(session, COMMAND_STATE); @@ -2340,7 +2102,7 @@ FTP_DECLARE(TYPE) FTP_DECLARE(USER) { - console_print("%s %s\n", __func__, args ? args : ""); + console_print(CYAN "%s %s\n" RESET, __func__, args ? args : ""); ftp_session_set_state(session, COMMAND_STATE); diff --git a/source/gfx.c b/source/gfx.c old mode 100755 new mode 100644 index 2fcd96e..664b9e3 --- a/source/gfx.c +++ b/source/gfx.c @@ -1,6 +1,6 @@ #ifdef _3DS +#include #include <3ds.h> -#endif #include @@ -30,4 +30,5 @@ void gfxDrawSprite(gfxScreen_t screen, gfx3dSide_t side, u8* spriteData, u16 wid { memcpy(&fbAdr[((x+xOffset)+(y+j)*fbWidth)*3], &spriteData[((xOffset)+(j)*width)*3], widthDrawn*3); } -} \ No newline at end of file +} +#endif diff --git a/source/main.c b/source/main.c index 4e105bd..fa4b095 100644 --- a/source/main.c +++ b/source/main.c @@ -69,7 +69,7 @@ main(int argc, /* initialize console subsystem */ console_init(); - console_set_status(STATUS_STRING); + console_set_status("\n" GREEN STATUS_STRING RESET); /* initialize ftp subsystem */ if(ftp_init() == 0) @@ -83,7 +83,6 @@ main(int argc, console_print("Press B to exit\n"); loop(wait_for_b); - console_exit(); #ifdef _3DS /* deinitialize 3DS services */