/**************************************************************************** * Copyright (C) 2013 FIX94 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . ****************************************************************************/ #include #include #include "FTP_Dir.hpp" #include "ftp.h" #include "net.h" #include "gecko/gecko.hpp" #include "devicemounter/DeviceHandler.hpp" #include "fileOps/fileOps.h" #include "gui/fmt.h" #include "loader/wbfs.h" #include "memory/mem2.hpp" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ char main_path[MAXPATHLEN]; char real_path[MAXPATHLEN]; u8 cur_part = 0; char dbg_messages[6][128]; void ftp_init(void) { memset(main_path, 0, MAXPATHLEN); main_path[0] = '/'; memset(real_path, 0, MAXPATHLEN); cur_part = 0; for(u8 i = 0; i < 6; ++i) memset(dbg_messages[i], 0, 128); } const char *ftp_getpath(void) { return main_path; } static bool check_device(void) { u8 i; cur_part = 0; for(i = 0; i < MAXDEVICES; ++i) { if(strncmp(DeviceName[i], main_path+1, strlen(DeviceName[i])) == 0) { cur_part = i; return true; } } return false; } static bool change_real_dir(void) { if(main_path[1] == '\0') return true; if(check_device() == true) { strncpy(real_path, fmt("%s:/%s", DeviceName[cur_part], strchr((main_path+1), '/')+1), MAXPATHLEN); if(!fsop_FolderExist(real_path)) { errno = ENOTDIR; return false; } return true; } errno = ENODEV; return false; } DIR *ftp_diropen() { DIR *cur_dir = NULL; if(main_path[1] != '\0') cur_dir = opendir(real_path); if(cur_dir == NULL) errno = EIO; return cur_dir; } int ftp_dirnext(DIR *dir, char *name) { int ret = -1; if(main_path[1] == '\0') { while(cur_part < MAXDEVICES) { if(DeviceHandle.IsInserted(cur_part) && DeviceHandle.GetFSType(cur_part) != PART_FS_WBFS) { strncpy(name, DeviceName[cur_part], 8); cur_part++; ret = 0; break; } cur_part++; } } else if(dir != NULL) { while(1) { struct dirent *pent = readdir(dir); if(pent == NULL) break; else if(pent->d_name[0] == '.') continue; strncpy(name, pent->d_name, MAXPATHLEN); ret = 0; break; } } return ret; } void ftp_dirclose(DIR *dir) { if(dir != NULL) closedir(dir); dir = NULL; } int ftp_changedir(char *path) { int ret = -1; /* main changing */ if(strcmp(path, "..") == 0) { /* not in root */ if(strlen(main_path) > 1) { /* remove new / */ if(strchr(main_path, '/') != NULL) { *(strrchr(main_path, '/')) = '\0'; /* remove the path before the new / */ if(strchr(main_path, '/') != NULL) *(strrchr(main_path, '/')+1) = '\0'; } } } else /* enter a new path, do some checks */ { if(path[0] == '/') /* full path */ strcpy(main_path, path); else strcat(main_path, path); } char *last = (main_path+strlen(main_path)-1); if(*last != '/') { *(last+1) = '/'; *(last+2) = '\0'; } if(change_real_dir() == true) ret = 0; return ret; } int ftp_makedir(char *path) { int ret = -1; if(strchr(path, '/') != NULL) { char *real_path = strrchr(path, '/') + 1; if(real_path != '\0') { *strrchr(path, '/') = '\0'; ftp_changedir(path); path = real_path; } } if(main_path[1] != '\0') { char *new_dir = fmt("%s%s", real_path, path); fsop_MakeFolder(new_dir); if(fsop_FolderExist(new_dir) == true) ret = 0; } if(ret < 0) errno = EACCES; return ret; } FILE *ftp_fopen(char *path, char *type) { FILE *fp = NULL; if(main_path[1] != '\0') { char *new_file = fmt("%s%s", real_path, path); fp = fopen(new_file, type); if(fp != NULL) gprintf("Opening file %s in type %s\n", new_file, type); } if(fp == NULL) errno = (strcmp(type, "rb") == 0 ? EACCES : EROFS); return fp; } void ftp_fclose(FILE *fp) { if(fp != NULL) { fclose(fp); gprintf("Closing file\n"); } fp = NULL; } int ftp_stat(char *file, struct stat *st) { if(file == NULL || st == NULL) return -1; st->st_mtime = 0; st->st_size = 0; st->st_mode = 0; if(main_path[1] == '\0') st->st_mode |= S_IFDIR; else stat(fmt("%s%s", real_path, file), st); return 0; } int ftp_rename(char *path, char *new_name) { int ret = -1; char *old_path = fmt("%s%s", real_path, path); char *new_path = fmt("%s%s", real_path, new_name); if(fsop_FileExist(old_path)) { gprintf("Renaming File %s to %s\n", old_path, new_path); ret = rename(old_path, new_path); } else if(fsop_FolderExist(old_path)) { gprintf("Renaming Folder %s to %s\n", old_path, new_path); ret = rename(old_path, new_path); } if(ret < 0) errno = EIO; return ret; } int ftp_delete(char *path) { int ret = -1; char *old_path = fmt("%s%s", real_path, path); if(fsop_FileExist(old_path)) { gprintf("%s is a file, deleting it\n", old_path); fsop_deleteFile(old_path); ret = 0; } else if(fsop_FolderExist(old_path)) { gprintf("%s is a folder, deleting it\n", old_path); fsop_deleteFolder(old_path); ret = 0; } if(ret < 0) errno = ENOENT; return ret; } lwp_t ftpThrdPtr = LWP_THREAD_NULL; u8 *ftpThrdStack = NULL; static const u32 ftpThrdStackSize = 81920; //we need a big stack for all the transfers volatile bool ftpThrd_running = false; bool end_ftp = false; s32 cur_server_num = -1; void *ftp_loopThrd(void *nothing) { while(end_ftp == false) { process_ftp_events(cur_server_num); usleep(100); } ftpThrd_running = false; return nothing; } bool ftp_startThread(void) { ftp_endTread(); if(create_server() == false) return false; cur_server_num = get_server_num(); if(cur_server_num < 0) return false; end_ftp = false; ftpThrd_running = true; ftpThrdStack = (u8*)MEM2_memalign(32, ftpThrdStackSize); if(ftpThrdStack != NULL) { memset(ftpThrdStack, 0, ftpThrdStackSize); DCFlushRange(ftpThrdStack, ftpThrdStackSize); LWP_CreateThread(&ftpThrdPtr, ftp_loopThrd, NULL, ftpThrdStack, ftpThrdStackSize, 64); return true; } return false; } void ftp_endTread(void) { if(ftpThrdPtr == LWP_THREAD_NULL) return; if(LWP_ThreadIsSuspended(ftpThrdPtr)) LWP_ResumeThread(ftpThrdPtr); end_ftp = true; while(ftpThrd_running) usleep(50); LWP_JoinThread(ftpThrdPtr, NULL); ftpThrdPtr = LWP_THREAD_NULL; if(ftpThrdStack != NULL) MEM2_free(ftpThrdStack); ftpThrdStack = NULL; end_server(); cur_server_num = -1; } bool dbg_msg_change = false; void ftp_dbg_print(char *dbg_info) { dbg_msg_change = true; /* for gecko and stuff */ gprintf(dbg_info); /* for our gui */ for(u8 i = 5; i > 0; --i) memcpy(dbg_messages[i], dbg_messages[i-1], 128); memcpy(dbg_messages[0], dbg_info, 127); *(dbg_messages[0]+127) = '\0'; } const char *ftp_get_prints(u8 i) { return dbg_messages[i]; } bool ftp_dbg_print_update(void) { if(dbg_msg_change) { dbg_msg_change = false; return true; } return false; } #ifdef __cplusplus } #endif /* __cplusplus */