From 20f29f60b8e84168dd25014b85afa81c6b61a646 Mon Sep 17 00:00:00 2001 From: mtheall Date: Wed, 7 Jan 2015 23:26:01 -0600 Subject: [PATCH 1/5] Replace console with one built-in to libctru --- data/sans.10.kerning.bin | Bin 576 -> 0 bytes data/sans.10.render.bin | Bin 6836 -> 0 bytes data/sans.12.kerning.bin | Bin 1164 -> 0 bytes data/sans.12.render.bin | Bin 9592 -> 0 bytes data/sans.14.kerning.bin | Bin 1320 -> 0 bytes data/sans.14.render.bin | Bin 11768 -> 0 bytes data/sans.16.kerning.bin | Bin 1644 -> 0 bytes data/sans.16.render.bin | Bin 14696 -> 0 bytes data/sans.8.kerning.bin | Bin 336 -> 0 bytes data/sans.8.render.bin | Bin 5544 -> 0 bytes include/console.h | 12 +- include/gfx.h | 7 +- source/console.c | 654 +-------------------------------------- source/ftp.c | 277 +++++++++-------- source/gfx.c | 5 +- source/main.c | 5 +- 16 files changed, 176 insertions(+), 784 deletions(-) delete mode 100644 data/sans.10.kerning.bin delete mode 100644 data/sans.10.render.bin delete mode 100644 data/sans.12.kerning.bin delete mode 100644 data/sans.12.render.bin delete mode 100644 data/sans.14.kerning.bin delete mode 100644 data/sans.14.render.bin delete mode 100644 data/sans.16.kerning.bin delete mode 100644 data/sans.16.render.bin delete mode 100644 data/sans.8.kerning.bin delete mode 100644 data/sans.8.render.bin mode change 100755 => 100644 source/gfx.c diff --git a/data/sans.10.kerning.bin b/data/sans.10.kerning.bin deleted file mode 100644 index f6b70eb07b317377a3a7d639a3e02c204993ccb1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 576 zcmZ9|F$%&!6h+b5P+WkWjg1x-qF9Qg78I52&Yg|_!d!S*gd84|KksL1tsU$6_THy@ zUxqi4WAkl!HO}C5m~+e_zlN9LUA?)3GuV6ge?E;fC75;?n$ximc_Q7_*-iy7Lf8e+L19!xkJCocUvGcL>vGcM0+0U8p JFguwq;U5^M(hvXu diff --git a/data/sans.10.render.bin b/data/sans.10.render.bin deleted file mode 100644 index 08da873cf6202a3fa4ac3c7a3b6ae34e6911e95c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6836 zcma)A2V7T25+00nRM3E)5~WB{vBY>9�Jqm!Pq0?1IMFv7R;2*rMsC8BH#+qsACZ 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 diff --git a/data/sans.12.kerning.bin b/data/sans.12.kerning.bin deleted file mode 100644 index 843d7967ac4328ffd767cc009d834a737335d157..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1164 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 a695;&p}cp4gk+j*f#9yA>V-4q)&By%=fGe9 diff --git a/data/sans.16.kerning.bin b/data/sans.16.kerning.bin deleted file mode 100644 index be40c26c1beb062e6f4c12f9262cd771e53e09c8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1644 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 G*Z(g_j}~hH diff --git a/data/sans.8.kerning.bin b/data/sans.8.kerning.bin deleted file mode 100644 index f95aff59e4fadc03944f5d21546de438b897a820..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 336 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 Ng-T(F%-l=W{{=PU(~STC 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..2c65cdd 100644 --- a/source/console.c +++ b/source/console.c @@ -9,321 +9,22 @@ #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; - } - - /* 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; + consoleSelect(&main_console); } /*! set status bar contents @@ -336,10 +37,11 @@ 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); va_end(ap); + consoleSelect(&main_console); } /*! add text to the console @@ -350,349 +52,20 @@ 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); 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 +80,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 8ba832c..1e6ffc3 100644 --- a/source/ftp.c +++ b/source/ftp.c @@ -165,6 +165,7 @@ static ftp_command_t ftp_commands[] = /*! number of ftp commands */ 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(); @@ -172,6 +173,7 @@ static inline int Errno(void) return -err; return err; } +#endif /*! compare ftp command descriptors * @@ -265,14 +267,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; } @@ -297,23 +299,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); if(rc != 0) - console_print("closesocket: %d %s\n", Errno(), strerror(Errno())); + console_print(RED "closesocket: %d %s\n" RESET, Errno(), strerror(Errno())); } /*! close command socket on ftp session @@ -335,7 +337,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)); @@ -370,14 +372,14 @@ ftp_session_close_file(ftp_session_t *session) ret = FSFILE_Close(session->fd); if(ret != 0) - console_print("FSFILE_Close: 0x%08X\n", (unsigned int)ret); + console_print(RED "FSFILE_Close: 0x%08X\n" RESET, (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 } @@ -401,7 +403,7 @@ ftp_session_open_file_read(ftp_session_t *session) FS_OPEN_READ, FS_ATTRIBUTE_NONE); if(ret != 0) { - console_print("FSUSER_OpenFile: 0x%08X\n", (unsigned int)ret); + console_print(RED "FSUSER_OpenFile: 0x%08X\n" RESET, (unsigned int)ret); return -1; } @@ -409,7 +411,7 @@ ftp_session_open_file_read(ftp_session_t *session) ret = FSFILE_GetSize(session->fd, &size); if(ret != 0) { - console_print("FSFILE_GetSize: 0x%08X\n", (unsigned int)ret); + console_print(RED "FSFILE_GetSize: 0x%08X\n" RESET, (unsigned int)ret); ftp_session_close_file(session); return -1; } @@ -422,7 +424,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; } @@ -430,7 +432,7 @@ 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; } @@ -462,7 +464,7 @@ ftp_session_read_file(ftp_session_t *session) session->buffer, sizeof(session->buffer)); if(ret != 0) { - console_print("FSFILE_Read: 0x%08X\n", (unsigned int)ret); + console_print(RED "FSFILE_Read: 0x%08X\n" RESET, (unsigned int)ret); return -1; } @@ -478,7 +480,7 @@ ftp_session_read_file(ftp_session_t *session) 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; } @@ -509,7 +511,7 @@ ftp_session_open_file_write(ftp_session_t *session) FS_OPEN_WRITE|FS_OPEN_CREATE, FS_ATTRIBUTE_NONE); if(ret != 0) { - console_print("FSUSER_OpenFile: 0x%08X\n", (unsigned int)ret); + console_print(RED "FSUSER_OpenFile: 0x%08X\n" RESET, (unsigned int)ret); return -1; } @@ -517,7 +519,7 @@ ftp_session_open_file_write(ftp_session_t *session) ret = FSFILE_SetSize(session->fd, 0); if(ret != 0) { - console_print("FSFILE_SetSize: 0x%08X\n", (unsigned int)ret); + console_print(RED "FSFILE_SetSize: 0x%08X\n" RESET, (unsigned int)ret); ftp_session_close_file(session); } #else @@ -525,7 +527,7 @@ ftp_session_open_file_write(ftp_session_t *session) 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 @@ -557,11 +559,11 @@ ftp_session_write_file(ftp_session_t *session) FS_WRITE_FLUSH); if(ret != 0) { - console_print("FSFILE_Write: 0x%08X\n", (unsigned int)ret); + console_print(RED "FSFILE_Write: 0x%08X\n" RESET, (unsigned int)ret); return -1; } else if(bytes == 0) - console_print("FSFILE_Write: wrote 0 bytes\n"); + console_print(RED "FSFILE_Write: wrote 0 bytes\n" RESET); /* adjust file position */ session->filepos += bytes; @@ -576,11 +578,11 @@ ftp_session_write_file(ftp_session_t *session) 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; @@ -602,7 +604,7 @@ ftp_session_close_cwd(ftp_session_t *session) /* close open directory handle */ ret = FSDIR_Close(session->fd); if(ret != 0) - console_print("FSDIR_Close: 0x%08X\n", (unsigned int)ret); + console_print(RED "FSDIR_Close: 0x%08X\n" RESET, (unsigned int)ret); session->fd = -1; #else int rc; @@ -610,7 +612,7 @@ ftp_session_close_cwd(ftp_session_t *session) /* 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 } @@ -632,7 +634,7 @@ ftp_session_open_cwd(ftp_session_t *session) FS_makePath(PATH_CHAR, session->cwd)); if(ret != 0) { - console_print("FSUSER_OpenDirectory: 0x%08X\n", (unsigned int)ret); + console_print(RED "FSUSER_OpenDirectory: 0x%08X\n" RESET, (unsigned int)ret); return -1; } #else @@ -640,7 +642,7 @@ ftp_session_open_cwd(ftp_session_t *session) 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 @@ -720,18 +722,18 @@ ftp_send_response(ftp_session_t *session, 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; @@ -791,18 +793,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; } @@ -838,7 +840,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; @@ -877,7 +879,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; @@ -892,7 +894,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); @@ -926,7 +928,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; } @@ -935,7 +937,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; @@ -945,7 +947,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)); @@ -971,7 +973,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; } @@ -1062,7 +1064,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) @@ -1072,7 +1074,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)) @@ -1083,7 +1085,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)) @@ -1100,7 +1102,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)) @@ -1136,48 +1138,32 @@ 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); 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 "FSUSER_OpenArchive: 0x%08X\n" RESET, (unsigned int)ret); + goto archive_fail; } /* 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 @@ -1185,7 +1171,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; } @@ -1205,7 +1191,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; } @@ -1216,7 +1202,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; } @@ -1225,14 +1211,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 @@ -1242,7 +1231,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; } @@ -1250,18 +1239,39 @@ 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: + ret = FSUSER_CloseArchive(NULL, &sdmcArchive); + if(ret != 0) + console_print(RED "FSUSER_CloseArchive: 0x%08X\n" RESET, (unsigned int)ret); + +archive_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 */ @@ -1284,13 +1294,13 @@ 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); /* 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 } @@ -1307,7 +1317,7 @@ 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())); else if(rc > 0) { if(pollinfo.revents & POLLIN) @@ -1316,7 +1326,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); } } @@ -1436,7 +1446,7 @@ list_transfer(ftp_session_t *session) ret = FSDIR_Read(session->fd, &entries, 1, &dent); if(ret != 0) { - console_print("FSDIR_Read: 0x%08X\n", (unsigned int)ret); + 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"); @@ -1480,7 +1490,7 @@ list_transfer(ftp_session_t *session) 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"); @@ -1506,10 +1516,10 @@ list_transfer(ftp_session_t *session) { 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); @@ -1552,10 +1562,10 @@ retrieve_transfer(ftp_session_t *session) { 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); @@ -1581,7 +1591,7 @@ store_transfer(ftp_session_t *session) { 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); @@ -1589,7 +1599,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 @@ -1622,7 +1631,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); @@ -1632,7 +1641,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); @@ -1641,7 +1650,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); @@ -1652,7 +1661,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); @@ -1677,7 +1686,7 @@ FTP_DECLARE(CWD) ret = FSDIR_Close(fd); if(ret != 0) - console_print("FSDIR_Close: 0x%08X\n", (unsigned int)ret); + console_print(RED "FSDIR_Close: 0x%08X\n" RESET, (unsigned int)ret); #else struct stat st; int rc; @@ -1685,7 +1694,7 @@ FTP_DECLARE(CWD) 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"); } @@ -1707,7 +1716,7 @@ FTP_DECLARE(DELE) int rc; #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); @@ -1718,14 +1727,14 @@ FTP_DECLARE(DELE) ret = FSUSER_DeleteFile(NULL, sdmcArchive, FS_makePath(PATH_CHAR, session->buffer)); if(ret != 0) { - console_print("FSUSER_DeleteFile: 0x%08X\n", (unsigned int)ret); + 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); 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 @@ -1735,7 +1744,7 @@ FTP_DECLARE(DELE) 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); @@ -1746,7 +1755,7 @@ 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) { @@ -1798,7 +1807,7 @@ FTP_DECLARE(MKD) int rc; #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); @@ -1809,14 +1818,14 @@ FTP_DECLARE(MKD) ret = FSUSER_CreateDirectory(NULL, sdmcArchive, FS_makePath(PATH_CHAR, session->buffer)); if(ret != 0) { - console_print("FSUSER_OpenDirectory: 0x%08X\n", (unsigned int)ret); + 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); 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 @@ -1826,7 +1835,7 @@ FTP_DECLARE(MKD) 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); @@ -1839,7 +1848,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); @@ -1848,13 +1857,13 @@ 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(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); @@ -1868,7 +1877,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)); @@ -1879,14 +1888,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 @@ -1894,7 +1903,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"); } @@ -1902,7 +1911,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"); } @@ -1914,14 +1923,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)); @@ -1948,7 +1957,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); @@ -2030,7 +2039,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); @@ -2039,7 +2048,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); @@ -2050,7 +2059,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); @@ -2061,7 +2070,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) { @@ -2120,7 +2129,7 @@ FTP_DECLARE(RMD) int rc; #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); @@ -2131,14 +2140,14 @@ FTP_DECLARE(RMD) ret = FSUSER_DeleteDirectory(NULL, sdmcArchive, FS_makePath(PATH_CHAR, session->buffer)); if(ret != 0) { - console_print("FSUSER_DeleteDirectory: 0x%08X\n", (unsigned int)ret); + 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); 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 @@ -2155,7 +2164,7 @@ FTP_DECLARE(RNFR) 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); @@ -2180,14 +2189,14 @@ FTP_DECLARE(RNFR) if(ret != 0) { - console_print("no such file or directory\n"); + 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); 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 @@ -2206,7 +2215,7 @@ FTP_DECLARE(RNTO) #endif 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); @@ -2230,14 +2239,14 @@ FTP_DECLARE(RNTO) sdmcArchive, FS_makePath(PATH_CHAR, session->buffer)); if(ret != 0) { - console_print("FSUSER_RenameFile/Directory: 0x%08X\n", (unsigned int)ret); + 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); 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 @@ -2249,7 +2258,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) { @@ -2302,7 +2311,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); @@ -2311,7 +2320,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); @@ -2323,7 +2332,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); @@ -2332,7 +2341,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); @@ -2341,7 +2350,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 6fb7a12..a4ebb0f --- a/source/gfx.c +++ b/source/gfx.c @@ -1,6 +1,6 @@ #ifdef _3DS +#include #include <3ds.h> -#endif /* Function to draw sprite, from smea/3ds_hb_menu */ void gfxDrawSprite(gfxScreen_t screen, gfx3dSide_t side, u8* spriteData, u16 width, u16 height, s16 x, s16 y) @@ -28,4 +28,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 d314c5c..c38711a 100644 --- a/source/main.c +++ b/source/main.c @@ -66,13 +66,13 @@ main(int argc, srvInit(); aptInit(); hidInit(NULL); - gfxInit(); + gfxInitDefault(); gfxSet3D(false); #endif /* 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) @@ -86,7 +86,6 @@ main(int argc, console_print("Press B to exit\n"); loop(wait_for_b); - console_exit(); #ifdef _3DS /* deinitialize 3DS services */ From 6a4b4f0355f0fca4fd889c22112d9cf009838cbe Mon Sep 17 00:00:00 2001 From: mtheall Date: Wed, 7 Jan 2015 23:30:22 -0600 Subject: [PATCH 2/5] Add logging support --- source/console.c | 4 ++++ source/ftp.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/source/console.c b/source/console.c index 2c65cdd..834c37a 100644 --- a/source/console.c +++ b/source/console.c @@ -25,6 +25,8 @@ console_init(void) consoleSetWindow(&main_console, 0, 1, 50, 29); consoleSelect(&main_console); + + consoleDebugInit(debugDevice_NULL); } /*! set status bar contents @@ -40,6 +42,7 @@ console_set_status(const char *fmt, ...) consoleSelect(&status_console); va_start(ap, fmt); vprintf(fmt, ap); + vfprintf(stderr, fmt, ap); va_end(ap); consoleSelect(&main_console); } @@ -56,6 +59,7 @@ console_print(const char *fmt, ...) va_start(ap, fmt); vprintf(fmt, ap); + vfprintf(stderr, fmt, ap); va_end(ap); } diff --git a/source/ftp.c b/source/ftp.c index 1e6ffc3..7b1aa67 100644 --- a/source/ftp.c +++ b/source/ftp.c @@ -1150,6 +1150,31 @@ ftp_init(void) goto archive_fail; } +#if ENABLE_LOGGING + /* initialize sdmc_dev */ + ret = sdmcInit(); + if(ret != 0) + { + console_print(RED "sdmcInit: 0x%08X\n" RESET, (unsigned int)ret); + goto sdmc_fail; + } + + /* 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) @@ -1260,6 +1285,18 @@ 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: + ret = sdmcExit(); + if(ret != 0) + console_print(RED "sdmcExit: 0x%08X\n" RESET, (unsigned int)ret); + +sdmc_fail: +#endif ret = FSUSER_CloseArchive(NULL, &sdmcArchive); if(ret != 0) console_print(RED "FSUSER_CloseArchive: 0x%08X\n" RESET, (unsigned int)ret); @@ -1297,6 +1334,17 @@ ftp_exit(void) 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) From 1ddbd3b9b4d7e226fddadf335fab67e8ac5c0767 Mon Sep 17 00:00:00 2001 From: mtheall Date: Wed, 7 Jan 2015 23:31:52 -0600 Subject: [PATCH 3/5] Update for r44 --- Makefile.3ds | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.3ds b/Makefile.3ds index 6f03a93..cc6c675 100644 --- a/Makefile.3ds +++ b/Makefile.3ds @@ -39,12 +39,12 @@ APP_AUTHOR := mtheall #--------------------------------------------------------------------------------- # options for code generation #--------------------------------------------------------------------------------- -ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=softfp +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 From f1be81814cf4ba3dd6f0896ff14528ce54f27543 Mon Sep 17 00:00:00 2001 From: mtheall Date: Wed, 7 Jan 2015 23:35:54 -0600 Subject: [PATCH 4/5] fix unterminated comment --- source/ftp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/ftp.c b/source/ftp.c index 7b1aa67..756e790 100644 --- a/source/ftp.c +++ b/source/ftp.c @@ -1339,7 +1339,7 @@ ftp_exit(void) if(fclose(stderr) != 0) console_print(RED "fclose: 0x%08X\n" RESET, errno); - /* deinitialize sdmc_dev + /* deinitialize sdmc_dev */ ret = sdmcExit(); if(ret != 0) console_print(RED "sdmcExit: 0x%08X\n" RESET, (unsigned int)ret); From 0ba3844ad807f4fd59b1aaf0e417af93f4a5e4b7 Mon Sep 17 00:00:00 2001 From: mtheall Date: Wed, 19 Aug 2015 13:25:34 -0500 Subject: [PATCH 5/5] Use sdmc_dev Enable UTF8 --- source/ftp.c | 442 +++++++++------------------------------------------ 1 file changed, 73 insertions(+), 369 deletions(-) diff --git a/source/ftp.c b/source/ftp.c index 756e790..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,16 +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]); -#ifdef _3DS -static inline int Errno(void) -{ - int err = SOC_GetErrno(); - if(err < 0) - return -err; - return err; -} -#endif - /*! compare ftp command descriptors * * @param[in] p1 left side of comparison (ftp_command_t*) @@ -198,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 */ @@ -233,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 * @@ -267,14 +223,14 @@ ftp_set_socket_nonblocking(int fd) flags = fcntl(fd, F_GETFL, 0); 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; } rc = fcntl(fd, F_SETFL, flags | O_NONBLOCK); 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; } @@ -299,7 +255,7 @@ ftp_closesocket(int fd, int connected) rc = getpeername(fd, (struct sockaddr*)&addr, &addrlen); 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); } else @@ -309,13 +265,13 @@ ftp_closesocket(int fd, int connected) /* shutdown connection */ rc = shutdown(fd, SHUT_RDWR); 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 */ - rc = closesocket(fd); + rc = close(fd); 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 @@ -367,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(RED "FSFILE_Close: 0x%08X\n" RESET, (unsigned int)ret); - session->fd = -1; -#else int rc; rc = close(session->fd); if(rc != 0) console_print(RED "close: %d %s\n" RESET, errno, strerror(errno)); session->fd = -1; -#endif } /*! open file for reading for ftp session @@ -393,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(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; struct stat st; @@ -437,7 +360,6 @@ ftp_session_open_file_read(ftp_session_t *session) return -1; } session->filesize = st.st_size; -#endif /* reset file position */ /* TODO: support REST command */ @@ -455,28 +377,9 @@ 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(RED "FSFILE_Read: 0x%08X\n" RESET, (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) { @@ -488,7 +391,6 @@ ftp_session_read_file(ftp_session_t *session) session->filepos += rc; return rc; -#endif } /*! open file for writing for ftp session @@ -502,27 +404,6 @@ 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(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 */ session->fd = open(session->buffer, O_WRONLY|O_CREAT|O_TRUNC, 0644); 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)); return -1; } -#endif /* reset file position */ /* TODO: support REST command */ @@ -548,32 +428,9 @@ 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(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; /* 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) @@ -588,7 +445,6 @@ ftp_session_write_file(ftp_session_t *session) session->filepos += rc; return rc; -#endif } /*! close current working directory for ftp session @@ -598,15 +454,6 @@ 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(RED "FSDIR_Close: 0x%08X\n" RESET, (unsigned int)ret); - session->fd = -1; -#else int rc; /* close open directory pointer */ @@ -614,7 +461,6 @@ ftp_session_close_cwd(ftp_session_t *session) if(rc != 0) console_print(RED "closedir: %d %s\n" RESET, errno, strerror(errno)); session->dp = NULL; -#endif } /*! open current working directory for ftp session @@ -626,18 +472,6 @@ 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(RED "FSUSER_OpenDirectory: 0x%08X\n" RESET, (unsigned int)ret); - return -1; - } -#else /* open current working directory */ session->dp = opendir(session->cwd); 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)); return -1; } -#endif return 0; } @@ -715,7 +548,10 @@ 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); @@ -731,7 +567,7 @@ ftp_send_response(ftp_session_t *session, console_print(GREEN "%s" RESET, buffer); rc = send(session->cmd_fd, buffer, to_send, 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) console_print(RED "only sent %u/%u bytes\n" RESET, (unsigned int)rc, (unsigned int)to_send); @@ -742,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) @@ -793,7 +627,7 @@ ftp_session_new(int listen_fd) new_fd = accept(listen_fd, (struct sockaddr*)&addr, &addrlen); 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; } @@ -840,7 +674,7 @@ ftp_session_new(int listen_fd) rc = getsockname(new_fd, (struct sockaddr*)&session->pasv_addr, &addrlen); 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_session_destroy(session); return; @@ -879,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(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_send_response(session, 425, "Failed to establish connection\r\n"); return -1; @@ -928,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(RED "socket: %d %s\n" RESET, Errno(), strerror(Errno())); + console_print(RED "socket: %d %s\n" RESET, errno, strerror(errno)); return -1; } @@ -937,7 +771,7 @@ ftp_session_connect(ftp_session_t *session) sizeof(session->peer_addr)); 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); session->data_fd = -1; return -1; @@ -973,7 +807,7 @@ ftp_session_read_command(ftp_session_t *session) if(rc < 0) { /* 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); return; } @@ -1064,7 +898,7 @@ ftp_session_poll(ftp_session_t *session) /* poll the selected socket */ rc = poll(&pollinfo, 1, 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) { if(pollinfo.revents != 0) @@ -1142,15 +976,6 @@ ftp_init(void) 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 */ ret = sdmcInit(); if(ret != 0) @@ -1159,6 +984,7 @@ ftp_init(void) goto sdmc_fail; } +#if ENABLE_LOGGING /* open log file */ FILE *fp = freopen("/ftbrony.log", "wb", stderr); if(fp == NULL) @@ -1196,7 +1022,7 @@ ftp_init(void) listenfd = socket(AF_INET, SOCK_STREAM, 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(); return -1; } @@ -1216,7 +1042,7 @@ ftp_init(void) rc = setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)); 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(); return -1; } @@ -1227,7 +1053,7 @@ ftp_init(void) rc = bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); 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(); return -1; } @@ -1236,7 +1062,7 @@ ftp_init(void) rc = listen(listenfd, 5); 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(); return -1; } @@ -1256,7 +1082,7 @@ ftp_init(void) rc = getsockname(listenfd, (struct sockaddr*)&serv_addr, &addrlen); 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(); return -1; } @@ -1264,7 +1090,7 @@ ftp_init(void) rc = gethostname(hostname, sizeof(hostname)); 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(); return -1; } @@ -1291,17 +1117,12 @@ ftruncate_fail: 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: -#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(); if(ret != 0) console_print(RED "fsExit: 0x%08X\n" RESET, (unsigned int)ret); @@ -1365,7 +1186,10 @@ ftp_loop(void) rc = poll(&pollinfo, 1, 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) { if(pollinfo.revents & POLLIN) @@ -1479,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(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 dirent *dent = readdir(session->dp); if(dent == NULL) @@ -1533,8 +1320,12 @@ 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) { @@ -1552,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; } @@ -1562,9 +1352,9 @@ list_transfer(ftp_session_t *session) { if(rc < 0) { - if(Errno() == EWOULDBLOCK) + if(errno == EWOULDBLOCK) 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 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(Errno() == EWOULDBLOCK) + if(errno == EWOULDBLOCK) 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 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(Errno() == EWOULDBLOCK) + if(errno == EWOULDBLOCK) 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); @@ -1723,19 +1513,6 @@ 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(RED "FSDIR_Close: 0x%08X\n" RESET, (unsigned int)ret); -#else struct stat st; int rc; @@ -1748,7 +1525,6 @@ FTP_DECLARE(CWD) 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)); @@ -1758,11 +1534,7 @@ FTP_DECLARE(CWD) FTP_DECLARE(DELE) { -#ifdef _3DS - Result ret; -#else - int rc; -#endif + int rc; console_print(CYAN "%s %s\n" RESET, __func__, args ? args : ""); @@ -1771,21 +1543,12 @@ FTP_DECLARE(DELE) 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(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); if(rc != 0) { 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"); } @@ -1796,7 +1559,7 @@ FTP_DECLARE(FEAT) 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) @@ -1849,11 +1612,7 @@ FTP_DECLARE(LIST) FTP_DECLARE(MKD) { -#ifdef _3DS - Result ret; -#else - int rc; -#endif + int rc; console_print(CYAN "%s %s\n" RESET, __func__, args ? args : ""); @@ -1862,21 +1621,12 @@ FTP_DECLARE(MKD) 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(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); if(rc != 0) { 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"); } @@ -1909,6 +1659,20 @@ FTP_DECLARE(NOOP) 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(CYAN "%s %s\n" RESET, __func__, args ? args : ""); @@ -1936,7 +1700,7 @@ FTP_DECLARE(PASV) session->pasv_fd = socket(AF_INET, SOCK_STREAM, 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"); } @@ -1951,7 +1715,7 @@ FTP_DECLARE(PASV) sizeof(session->pasv_addr)); 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); return ftp_send_response(session, 451, "\r\n"); } @@ -1959,7 +1723,7 @@ FTP_DECLARE(PASV) rc = listen(session->pasv_fd, 5); 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); return ftp_send_response(session, 451, "\r\n"); } @@ -1971,7 +1735,7 @@ FTP_DECLARE(PASV) &addrlen); 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); return ftp_send_response(session, 451, "\r\n"); } @@ -2171,11 +1935,7 @@ FTP_DECLARE(RETR) FTP_DECLARE(RMD) { -#ifdef _3DS - Result ret; -#else - int rc; -#endif + int rc; console_print(CYAN "%s %s\n" RESET, __func__, args ? args : ""); @@ -2184,34 +1944,20 @@ FTP_DECLARE(RMD) 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(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); if(rc != 0) { 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(CYAN "%s %s\n" RESET, __func__, args ? args : ""); ftp_session_set_state(session, COMMAND_STATE); @@ -2219,35 +1965,12 @@ FTP_DECLARE(RNFR) 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(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); if(rc != 0) { 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; @@ -2256,11 +1979,7 @@ FTP_DECLARE(RNFR) FTP_DECLARE(RNTO) { -#ifdef _3DS - Result ret; -#else - int rc; -#endif + int rc; char buffer[XFER_BUFFERSIZE]; console_print(CYAN "%s %s\n" RESET, __func__, args ? args : ""); @@ -2277,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(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); if(rc != 0) { 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"); }