From 30fa41766baaeb061ab63870e4a13d54fa48ceb4 Mon Sep 17 00:00:00 2001 From: heredog <382138645@qq.com> Date: Thu, 5 Dec 2024 23:21:31 -0800 Subject: [PATCH 1/3] it's not rtc0 --- bsp/qemu-virt64-aarch64/drivers/drv_rtc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bsp/qemu-virt64-aarch64/drivers/drv_rtc.c b/bsp/qemu-virt64-aarch64/drivers/drv_rtc.c index 238e50074b..cb1fdeffe7 100644 --- a/bsp/qemu-virt64-aarch64/drivers/drv_rtc.c +++ b/bsp/qemu-virt64-aarch64/drivers/drv_rtc.c @@ -113,8 +113,8 @@ int rt_hw_rtc_init(void) rtc_device.device.user_data = RT_NULL; /* register a rtc device */ - rt_device_register(&rtc_device.device, "rtc0", RT_DEVICE_FLAG_RDWR); - rt_soft_rtc_set_source("rtc0"); + rt_device_register(&rtc_device.device, "rtc", RT_DEVICE_FLAG_RDWR); + rt_soft_rtc_set_source("rtc"); return 0; } INIT_DEVICE_EXPORT(rt_hw_rtc_init); -- Gitee From d13b4b94ff0eef7e010acc07b5f9dd82b0233d9d Mon Sep 17 00:00:00 2001 From: heredog <382138645@qq.com> Date: Wed, 11 Dec 2024 00:26:03 -0800 Subject: [PATCH 2/3] time long int --- components/libc/compilers/common/ctime.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/components/libc/compilers/common/ctime.c b/components/libc/compilers/common/ctime.c index 7c236f3da8..0eadb6079e 100644 --- a/components/libc/compilers/common/ctime.c +++ b/components/libc/compilers/common/ctime.c @@ -347,7 +347,10 @@ rt_weak time_t time(time_t *t) rt_set_errno(EFAULT); return (time_t)-1; } - + + if (sizeof(time_t) > 4) + _t = (int)_t; + if (t) *t = _t; -- Gitee From 052a366ddb533c7c547def4eeff3f4cd0dacb63c Mon Sep 17 00:00:00 2001 From: heredog <382138645@qq.com> Date: Mon, 16 Dec 2024 02:19:28 -0800 Subject: [PATCH 3/3] ftp server --- bsp/qemu-virt64-aarch64/applications/main.c | 75 +++ .../applications/mp_ftpd.c | 552 ++++++++++++++++++ .../applications/mp_ftpd.h | 8 + 3 files changed, 635 insertions(+) create mode 100644 bsp/qemu-virt64-aarch64/applications/mp_ftpd.c create mode 100644 bsp/qemu-virt64-aarch64/applications/mp_ftpd.h diff --git a/bsp/qemu-virt64-aarch64/applications/main.c b/bsp/qemu-virt64-aarch64/applications/main.c index 4447a4f47d..e16147f940 100644 --- a/bsp/qemu-virt64-aarch64/applications/main.c +++ b/bsp/qemu-virt64-aarch64/applications/main.c @@ -9,10 +9,85 @@ */ #include +#include "lwip/pbuf.h" +#include "lwip/tcp.h" +#include "lwip/udp.h" +#include +#include "unistd.h" +#include "dirent.h" +#include "ctype.h" +#include "sys/stat.h" +#include "time.h" +#include +char buf[1024] = {0x00}; int main(void) { + static const char months[] = "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec "; + extern bool mp_ftpd_init(); rt_kprintf("hello rt-thread\n"); + mp_ftpd_init(); + + DIR *dir = opendir("/mnt/ccc/"); + if (dir != NULL) { + int pos = 0; + struct dirent *entry; + struct stat statbuf; + struct tm* filetm; + long filesize = 0; + char filename[512]; + + time_t now = time(NULL); + memset(buf, 0x00, 1024); + printf("open ok!\r\n"); + // perms link user group file size datetime name + //"drwxrwxr-x 25 1000 1000 4096 Dec 08 18:02 u-boot\r\n" + //-rw-rw-r-- 1 1000 1000 1509820582 Dec 05 17:17 rt-thread.zip\r\n + while ((entry = readdir(dir)) != NULL) { + filesize = 0; + sprintf(filename, "/mnt/%s", entry->d_name); + if (stat(filename, &statbuf) > -1) { + filesize = statbuf.st_size; + filetm = localtime(&statbuf.st_mtime); + } else { + if (entry->d_type == 8) { + FILE* fp = fopen(filename, "r"); + if (fp != NULL) { + fseek(fp, 0, SEEK_END); + filesize = ftell(fp); + fclose(fp); + } + } + filetm = localtime(&now); + } + + if (entry->d_type == 4) { + strcpy(buf+pos, "drwxrwxr-x "); + } else { + strcpy(buf+pos, "-rw-rw-r-- "); + } + pos += strlen(buf+pos); + + sprintf(buf+pos, "1 "); // link default 1 + pos += strlen(buf+pos); + sprintf(buf+pos, "user "); //user + pos += strlen(buf+pos); + sprintf(buf+pos, "group "); //group id + pos += strlen(buf+pos); + + sprintf(buf+pos, "%ld ", filesize); //file size + pos += strlen(buf+pos); + + memcpy(buf+pos, months+(filetm->tm_mon << 2), 4); //datetime + pos += 4; + sprintf(buf+pos, "%02d %02d:%02d", filetm->tm_mday, filetm->tm_hour, filetm->tm_min); + pos += strlen(buf+pos); + sprintf(buf+pos, " %s\r\n", entry->d_name); //file name + pos += strlen(buf+pos); + } + rt_kprintf(buf); + closedir(dir); + } return 0; } diff --git a/bsp/qemu-virt64-aarch64/applications/mp_ftpd.c b/bsp/qemu-virt64-aarch64/applications/mp_ftpd.c new file mode 100644 index 0000000000..9bd7963959 --- /dev/null +++ b/bsp/qemu-virt64-aarch64/applications/mp_ftpd.c @@ -0,0 +1,552 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020/10/7 bernard the first version + */ + +#include "mp_ftpd.h" + +#include "lwip/pbuf.h" +#include "lwip/tcp.h" +#include "lwip/udp.h" + +#include +#include + +#include "unistd.h" +#include "dirent.h" +#include "ctype.h" +#include "sys/stat.h" +#include "time.h" + +#define FILE_PATH_MAX 256 + +#define MP_FTP_PORT 21 +#define MP_PASV_PORT 30972 +#define DEBUG_printf rt_kprintf +#define BUF_SIZE 1024 + +typedef void(*mp_ftpd_accept_func)(void* arg); +typedef void(*mp_ftpd_sent_func)(void* arg); +typedef void(*mp_ftpd_recv_func)(char* data, uint16_t size); + +typedef struct mp_ftpd_state +{ + struct tcp_pcb *server_pcb; + struct tcp_pcb *client_pcb; + bool is_sending; + bool send_wait; + + mp_ftpd_recv_func recv_func; + mp_ftpd_sent_func sent_func; + mp_ftpd_accept_func accept_func; + +} mp_ftpd_state; + +static mp_ftpd_state ftpd_cmd; +static mp_ftpd_state ftpd_pasv; +static char curr_path[FILE_PATH_MAX]; +static FILE* f_upload = NULL; +static FILE* f_download = NULL; +static long f_downsize = 0; +static DIR* f_opendir = NULL; + +struct tcp_pcb* mp_ftpd_create(u16_t port, void *arg); +static err_t mp_ftpd_accept(void *arg, struct tcp_pcb *client_pcb, err_t err); +static err_t mp_ftpd_sent(void *arg, struct tcp_pcb *tpcb, uint16_t len); +static err_t mp_ftpd_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err); +static err_t mp_ftpd_send(mp_ftpd_state *state, const void* data, uint16_t size); +static void mp_ftpd_fclose(void); +static err_t mp_ftpd_close(mp_ftpd_state *state); +static void mp_ftpd_err(void *arg, err_t err); + + +static void mp_ftpd_welcome(void* arg); +static void mp_ftpd_parse(char* data, uint16_t size); +static void mp_ftpd_cmdlist(void* arg); +static void mp_ftpd_cmdretr(void* arg); +static void mp_ftpd_cmdstor(char* data, uint16_t size); + + +bool mp_ftpd_init(void) +{ + mp_ftpd_state *cmd = &ftpd_cmd; + mp_ftpd_state *pasv = &ftpd_pasv; + + memset(cmd, 0x00, sizeof(mp_ftpd_state)); + memset(pasv, 0x00, sizeof(mp_ftpd_state)); + + DEBUG_printf("mp_ftpd:init ftp server!\n"); + cmd->accept_func = mp_ftpd_welcome; + cmd->recv_func = mp_ftpd_parse; + cmd->server_pcb = mp_ftpd_create(MP_FTP_PORT, cmd); + pasv->server_pcb = mp_ftpd_create(MP_PASV_PORT, pasv); + return true; +} + + +void mp_ftpd_parse(char* data, uint16_t size) +{ + char cmd[16] = {0x00}; + char buf[512] = {0x00}; + if (size < 1) { //client close. + return; + } + + sscanf(data, "%s %s", cmd, buf); + DEBUG_printf("CMD:%s\r\n", cmd); + int i = 0; + do { + cmd[i] = toupper(cmd[i]); //command to upper + } while (cmd[++i]); + + if (strcmp(cmd, "USER") == 0) { + mp_ftpd_puts("331 Please specify the password.\r\n"); + } else if (strcmp(cmd, "PASS") == 0) { + mp_ftpd_puts("230 Login successful.\r\n"); + } else if (strcmp(cmd, "OPTS") == 0) { + mp_ftpd_puts("200 Always OPTS mode.\r\n"); + } else if (strcmp(cmd, "PWD") == 0) { + sprintf(buf, "257 \"%s\"is current directory.\r\n", curr_path); + mp_ftpd_puts(buf); + } else if (strcmp(cmd, "CWD") == 0) { + if (buf[0] == '/') { + strcpy(curr_path, buf); + } else { + strcat(curr_path, buf); + } + size = strlen(curr_path); + if (curr_path[size-1] != '/') { + curr_path[size] = '/'; + } + DEBUG_printf("mp_ftpd:current path:%s\r\n", curr_path); + mp_ftpd_puts("250 dir successfully changed.\r\n"); + } else if (strcmp(cmd, "TYPE") == 0) { + if (buf[0] == 'A') { + mp_ftpd_puts("200 Switching to ASCII mode.\r\n"); + } else if (buf[0] == 'I') { + mp_ftpd_puts("200 Switching to Binary mode.\r\n"); + } else { + mp_ftpd_puts("504 Command not implemented for that parameter.\r\n"); + } + } else if (strcmp(cmd, "PASV") == 0) { + ip_addr_t ip = ftpd_cmd.client_pcb->local_ip; + uint16_t port = MP_PASV_PORT; + sprintf(buf, "227 Entering Passive Mode (%d, %d, %d, %d, %d, %d).\r\n", + ip4_addr1(&ip), ip4_addr2(&ip), ip4_addr3(&ip), ip4_addr4(&ip), + (port>>8)&0xFF, port&0xFF); + mp_ftpd_puts(buf); + } else if (strcmp(cmd, "LIST") == 0) { //file list + DIR *dir = opendir(curr_path); + f_opendir = dir; + ftpd_cmd.sent_func = mp_ftpd_cmdlist; + mp_ftpd_puts("150 Here comes the directory listing.\r\n"); + + + + } else if (strcmp(cmd, "STOR") == 0) { //file upload + char filename[1024]; + sprintf(filename, "%s/%s", curr_path, buf); + f_upload = fopen(filename, "wb"); + ftpd_pasv.recv_func = mp_ftpd_cmdstor; + mp_ftpd_puts("150 Ok to send data.\r\n"); + } else if(strcmp(cmd, "NOOP") == 0) { + mp_ftpd_puts("200 NOOP ok.\r\n"); + } else if (strcmp(cmd, "SIZE") == 0) { //file size + char filename[1024]; + sprintf(filename, "%s/%s", curr_path, buf); + FILE* fp = fopen(filename, "r"); + if (fp != NULL) { + fseek(fp, 0, SEEK_END); + f_downsize = ftell(fp); + fclose(fp); + } + sprintf(filename, "213 %ld\r\n", f_downsize); + mp_ftpd_puts(filename); + } else if (strcmp(cmd, "RETR") == 0) { //file download + char filename[1024]; + sprintf(filename, "%s/%s", curr_path, buf); + FILE* fp = fopen(filename, "r"); + if (fp != NULL) { + f_download = fp; + ftpd_cmd.sent_func = mp_ftpd_cmdretr; + sprintf(filename, "150 Opening BINARY mode data connection for %s (%ld bytes).\r\n", + buf, f_downsize); + mp_ftpd_puts(filename); + } else { + mp_ftpd_puts("550 Failed to read file.\r\n"); + } + + } else if (strcmp(cmd, "RMD") == 0) { + char path[1024]; + sprintf(path, "%s%s", curr_path, buf); + DEBUG_printf("mp_ftpd:delete path %s", path); + if (rmdir(path) > -1) { + mp_ftpd_puts("250 Delete operation successful.\r\n"); + } else { + mp_ftpd_puts("550 Cannot delete directory.\r\n"); + } + } else if (strcmp(cmd, "DELE") == 0) { + char filename[1024]; + sprintf(filename, "%s/%s", curr_path, buf); + + if (unlink(filename) > -1) { + mp_ftpd_puts("250 Delete operation successful.\r\n"); + } else { + mp_ftpd_puts("550 File unavailable.\n"); + } + } else if (strcmp(cmd, "MKD") == 0) { //create dir + char path[1024]; + sprintf(path, "%s/%s", curr_path, buf); + mkdir(path, S_IRWXG); + sprintf(path, "257 \"%s/%s\" created\r\n", curr_path, buf); + mp_ftpd_puts(path); + } else if (strcmp(cmd, "RNFR") == 0) { //ready RNTO + char path[1024]; + sprintf(path, "%s/%s", curr_path, buf); + strcpy(curr_path, path); + mp_ftpd_puts("350 Ready for RNTO.\r\n"); + } else if (strcmp(cmd, "RNTO") == 0) { //rename file or dir + char old_filename[FILE_PATH_MAX]; + char new_filename[1024]; + char* path_end = strrchr(curr_path, '/'); + strcpy(old_filename, curr_path); + if (path_end != NULL) { + path_end[0] = '\0'; + sprintf(new_filename, "%s/%s", curr_path, buf); + rename(old_filename, new_filename); + mp_ftpd_puts("250 Rename successful.\r\n"); + } else { + mp_ftpd_puts("550 File unavailable.\r\n"); + } + } else if (strcmp(cmd, "SYST") == 0) { + mp_ftpd_puts("215 UNIX Type: L8\r\n"); + } else if (strcmp(cmd, "SITE") == 0) { + mp_ftpd_puts("214 CHMOD UMASK HELP\r\n"); + } else if (strcmp(cmd, "ABOR") == 0) { + mp_ftpd_fclose(); + mp_ftpd_puts("226 Closing data connection.\r\n"); + } else if (strcmp(cmd, "QUIT") == 0) { + mp_ftpd_fclose(); + mp_ftpd_puts("221 Goodbye, friend.\r\n"); + } +} + +void mp_ftpd_welcome(void* arg) +{ + getcwd(curr_path, FILE_PATH_MAX); + mp_ftpd_puts("200 (mpFTPd 1.0.0)\r\n"); +} + +void mp_ftpd_cmdretr(void* arg) +{ + ftpd_cmd.sent_func = NULL; + + size_t size = 0; + char buf[1024]; + + if (f_download != NULL && (size = fread(buf, 1, 1024, f_download)) > 0) { + ftpd_pasv.sent_func = mp_ftpd_cmdretr; // prepare next send + mp_ftpd_send(&ftpd_pasv, buf, size); + } else { + if (f_download!= NULL) { + fclose(f_download); + f_download = NULL; + } + ftpd_pasv.sent_func = NULL; + mp_ftpd_close(&ftpd_pasv); + mp_ftpd_puts("226 Transfer complete.\r\n"); + } +} + +void mp_ftpd_cmdstor(char* data, uint16_t size) //upload file +{ + if (size > 0) { + if (f_upload != NULL) { + fwrite(data, size, 1, f_upload); + } + } else { + fclose(f_upload); + f_upload = NULL; + ftpd_pasv.sent_func = NULL; + mp_ftpd_puts("226 Transfer complete.\r\n"); + } + +} + +static const char months[] = "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec "; +void mp_ftpd_cmdlist(void* arg) +{ + + char buf[1024] = {0x00}; + + ftpd_cmd.sent_func = NULL; + + if (f_opendir != NULL) { + + struct dirent *entry; + struct stat statbuf; + struct tm* filetm; + long filesize = 0; + char filename[512]; + int max = 1024 - FILE_PATH_MAX; + int pos = 0; + time_t now = time(NULL); + memset(buf, 0x00, 1024); + DEBUG_printf("open dir:%s\r\n", curr_path); + + // perms link user group file size datetime name + //"drwxr-xr-x 25 1000 1000 4096 Dec 08 18:02 u-boot\r\n" + //-rw-rw-r-- 1 1000 1000 1509820582 Dec 05 17:17 rt-thread.zip\r\n + while ((entry = readdir(f_opendir)) != NULL && pos < max) { + filesize = 0; + + sprintf(filename, "%s/%s", curr_path, entry->d_name); + if (stat(filename, &statbuf) > -1) { + filesize = statbuf.st_size; + filetm = localtime(&statbuf.st_mtime); + } else { + if (entry->d_type == 8) { // isfile + FILE* fp = fopen(filename, "r"); + if (fp != NULL) { + fseek(fp, 0, SEEK_END); + filesize = ftell(fp); + fclose(fp); + } + } + filetm = localtime(&now); + } + DEBUG_printf("mp_ftpd:%s\r\n", entry->d_name); + if (entry->d_type == 4) { // dir + filesize = 4096; + strcpy(buf+pos, "drwxr-xr-x "); + } else { + strcpy(buf+pos, "-rw-rw-r-- "); + } + pos += strlen(buf+pos); + + sprintf(buf+pos, "2 "); // link default 1 + pos += strlen(buf+pos); + sprintf(buf+pos, "1000 "); //user + pos += strlen(buf+pos); + sprintf(buf+pos, "1000 "); //group id + pos += strlen(buf+pos); + + sprintf(buf+pos, "%ld ", filesize); //file size + pos += strlen(buf+pos); + + memcpy(buf+pos, months+(filetm->tm_mon << 2), 4); //datetime + pos += 4; + sprintf(buf+pos, "%02d %02d:%02d", filetm->tm_mday, filetm->tm_hour, filetm->tm_min); + pos += strlen(buf+pos); + + sprintf(buf+pos, " %s\r\n", entry->d_name); //file name + pos += strlen(buf+pos); + } + + + if (pos > 0) { + ftpd_pasv.sent_func = mp_ftpd_cmdlist; // prepare next send + mp_ftpd_send(&ftpd_pasv, buf, pos); + } else { + closedir(f_opendir); + f_opendir = NULL; + ftpd_pasv.sent_func = NULL; + mp_ftpd_close(&ftpd_pasv); + mp_ftpd_puts("226 Directory send OK.\r\n"); + } + } else { + ftpd_pasv.sent_func = NULL; + mp_ftpd_close(&ftpd_pasv); + mp_ftpd_puts("550 Failed to open directory.\r\n"); + DEBUG_printf("mp_ftpd:open dir fail:%s\r\n", curr_path); + } +} + + +struct tcp_pcb* mp_ftpd_create(u16_t port, void *arg) +{ + err_t err; + struct tcp_pcb *pcb = tcp_new_ip_type(IPADDR_TYPE_ANY); + if (!pcb) { + DEBUG_printf("mp_ftpd:failed to create pcb\n"); + return NULL; + } + err = tcp_bind(pcb, NULL, port); + if (err) { + DEBUG_printf("mp_ftpd:failed to bind to port %u\n", port); + return NULL; + } + pcb = tcp_listen_with_backlog(pcb, 1); + if (!pcb) { + DEBUG_printf("mp_ftpd:failed to listen\n"); + if (pcb) { + tcp_close(pcb); + } + return NULL; + } + + tcp_arg(pcb, arg); + tcp_accept(pcb, mp_ftpd_accept); + return pcb; +} + + +err_t mp_ftpd_accept(void *arg, struct tcp_pcb *client_pcb, err_t err) +{ + mp_ftpd_state *state = (mp_ftpd_state*)arg; + if (err != ERR_OK || client_pcb == NULL) { + DEBUG_printf("mp_ftpd:failure in accept\n"); + return ERR_VAL; + } + + if (state->client_pcb != NULL) { + mp_ftpd_close(state); // close prev client. + } + + tcp_arg(client_pcb, state); + tcp_sent(client_pcb, mp_ftpd_sent); + tcp_recv(client_pcb, mp_ftpd_recv); + tcp_err(client_pcb, mp_ftpd_err); + + if (state == &ftpd_cmd) { + DEBUG_printf("mp_ftpd:client connected\n"); + } else { + DEBUG_printf("mp_ftpdata:client connected\n"); + } + state->client_pcb = client_pcb; + + if (state->accept_func) { + state->accept_func(arg); + } + + return err; +} + +void mp_ftpd_puts(char *data) +{ + mp_ftpd_state *state = &ftpd_cmd; + mp_ftpd_send(state, data, strlen(data)); +} + +err_t mp_ftpd_send(mp_ftpd_state *state, const void* data, uint16_t size) +{ + err_t err = ERR_CLSD; + + if (state->client_pcb != NULL && size > 0) { + DEBUG_printf("mp_ftpd:writing %d bytes\r\n", size); + if (!state->is_sending) { + state->is_sending = true; + err = tcp_write(state->client_pcb, data, size, TCP_WRITE_FLAG_COPY); + if (err != ERR_OK) { + DEBUG_printf("mp_ftpd:failed to write: %d\r\n", err); + return err; + } + + err = tcp_output(state->client_pcb); + if (err != ERR_OK) { + DEBUG_printf("mp_ftpd:failed to output %d\r\n", err); + return err; + } + } + + return err; + } + return ERR_ISCONN; +} + +err_t mp_ftpd_sent(void *arg, struct tcp_pcb *tpcb, u16_t len) +{ + (void)arg; + (void)tpcb; + mp_ftpd_state *state = (mp_ftpd_state *)arg; + state->is_sending = false; + if (state->sent_func != NULL) { + state->sent_func(arg); + } + return ERR_OK; +} + +err_t mp_ftpd_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *buf, err_t err) +{ + struct pbuf *p; + mp_ftpd_state *state = (mp_ftpd_state*)arg; + + if (!buf) { //tcp close + if (state->recv_func != NULL) { + state->recv_func(NULL, 0); + } + return mp_ftpd_close(state); + } + + if (buf->tot_len > 0) { + tcp_recved(tpcb, buf->tot_len); + for (p = buf; p != NULL; p = p->next) { + if (state->recv_func != NULL) { + state->recv_func(p->payload, p->len); + } + } + + } + pbuf_free(buf); + + return err; +} + +void mp_ftpd_fclose(void) +{ + if (f_download != NULL) { + fclose(f_download); + } + if (f_upload != NULL) { + fclose(f_upload); + } + f_download = NULL; + f_upload = NULL; + f_downsize = 0; +} + +err_t mp_ftpd_close(mp_ftpd_state *state) +{ + err_t err = ERR_OK; + if (state->client_pcb != NULL) { + struct tcp_pcb *client_pcb = state->client_pcb; + + tcp_arg(client_pcb, NULL); + tcp_poll(client_pcb, NULL, 0); + tcp_sent(client_pcb, NULL); + tcp_recv(client_pcb, NULL); + tcp_err(client_pcb, NULL); + err = tcp_close(client_pcb); + + if (err != ERR_OK) { + DEBUG_printf("mp_ftpd:close failed %d, calling abort\r\n", err); + tcp_abort(client_pcb); + err = ERR_ABRT; + } + state->is_sending = false; + state->client_pcb = NULL; + if (state == &ftpd_cmd) { + DEBUG_printf("mp_ftpd:client close.\r\n"); + } else { + DEBUG_printf("mp_ftpdata:client close.\r\n"); + } + } + + mp_ftpd_fclose(); + + return err; +} + +void mp_ftpd_err(void *arg, err_t err) +{ + mp_ftpd_state *state = (mp_ftpd_state*)arg; + if (err != ERR_ABRT) { + DEBUG_printf("mp_ftpd:err: %d\n", err); + mp_ftpd_close(state); + } +} \ No newline at end of file diff --git a/bsp/qemu-virt64-aarch64/applications/mp_ftpd.h b/bsp/qemu-virt64-aarch64/applications/mp_ftpd.h new file mode 100644 index 0000000000..3b402a3473 --- /dev/null +++ b/bsp/qemu-virt64-aarch64/applications/mp_ftpd.h @@ -0,0 +1,8 @@ +#ifndef MP_FTPD_H +#define MP_FTPD_H +#include + +bool mp_ftpd_init(void); +void mp_ftpd_puts(char *data); + +#endif \ No newline at end of file -- Gitee