diff --git a/.gitignore b/.gitignore index 96374c4..1a97e94 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,14 @@ $RECYCLE.BIN/ Network Trash Folder Temporary Items .apdisk +saviine/installer/bin/* +saviine/client/build/* +saviine/server/src/bin/logs/* +saviine/server/src/bin/saviine_root/* +saviine/server/src/bin/saviine_server.pdb +saviine/server/src/bin/saviine_server.vshost.exe.manifest +saviine/server/src/obj/x86/Debug/saviine_server.exe +saviine/server/src/obj/x86/Debug/saviine_server.pdb +saviine/server/src/bin/saviine_server.vshost.exe +saviine/server/src/bin/saviine_server.exe.config +saviine/server/src/bin/saviine_server.vshost.exe.config diff --git a/saviine/client/main.c b/saviine/client/main.c index 45ff416..ce65636 100644 --- a/saviine/client/main.c +++ b/saviine/client/main.c @@ -4,10 +4,7 @@ extern res name(__VA_ARGS__); \ res (* real_ ## name)(__VA_ARGS__) __attribute__((section(".magicptr"))); \ res my_ ## name(__VA_ARGS__) - -#define BYTE_LOG_STR 0xfb - - +#define DEBUG_LOG 0 extern FSStatus FSOpenDir(FSClient *pClient, FSCmdBlock *pCmd, const char *path, int *dh, FSRetFlag errHandling); extern FSStatus FSReadDir(FSClient *pClient, FSCmdBlock *pCmd, int dh, FSDirEntry *dir_entry, FSRetFlag errHandling); extern FSStatus FSChangeDir(FSClient *pClient, FSCmdBlock *pCmd, const char *path, FSRetFlag errHandling); @@ -15,17 +12,13 @@ extern FSStatus FSCloseDir(FSClient *pClient, FSCmdBlock *pCmd, int dh, FSRetFla extern FSStatus FSReadFile(FSClient *pClient, FSCmdBlock *pCmd, void *buffer, int size, int count, int fd, int flag, int error); extern FSStatus FSSetPosFile(FSClient *pClient, FSCmdBlock *pCmd, int fd, int pos, int error); extern FSStatus FSCloseFile (FSClient *pClient, FSCmdBlock *pCmd, int fd, int error); +extern FSStatus FSMakeDir(FSClient *pClient, FSCmdBlock *pCmd,const char *path, FSRetFlag errHandling); +extern FSStatus FSRemove(FSClient *pClient, FSCmdBlock *pCmd, const char *path, FSRetFlag errHandling); extern void OSDynLoad_Acquire (char* rpl, unsigned int *handle); extern void OSDynLoad_FindExport (unsigned int handle, int isdata, char *symbol, void *address); void GX2WaitForVsync(void); -static void dump_saves(void *pClient, void *pCmd,int error, int client); - -static int strlen(char* path) { - int i = 0; - while (path[i++]) - ; - return i; -} +static void handle_saves(void *pClient, void *pCmd,int error, int client); +static void hook(void * pClient,void * pCmd, int error, int client); DECL(int, FSAInit, void) { if ((int)bss_ptr == 0x0a000000) { @@ -56,6 +49,31 @@ DECL(int, FSADelClient, int client) { return real_FSADelClient(client); } +static int strlen(char* path) { + int i = 0; + while (path[i++]) + ; + return i; +} + +static int strcmp(const char *s1, const char *s2) +{ + while(*s1 && *s2) + { + if(*s1 != *s2) { + return -1; + } + s1++; + s2++; + } + + if(*s1 != *s2) { + return -1; + } + return 0; +} + + static int client_num_alloc(void *pClient) { int i; @@ -100,8 +118,17 @@ DECL(int, FSDelClient, void *pClient) { } return real_FSDelClient(pClient); } +DECL(int, FSWriteFile,FSClient *pClient, FSCmdBlock *pCmd, const void *source,int size, int count, int fileHandle, int flag,FSRetFlag error) { +return real_FSWriteFile(pClient,pCmd,source,size,count,fileHandle,flag,error); +} + +DECL(int, FSFlushQuota,FSClient *pClient,FSCmdBlock *pCmd,const char *path,FSRetFlag error) { +return real_FSFlushQuota(pClient,pCmd,path,error); +} + DECL(int, FSAddClientEx, void *r3, void *r4, void *r5) { int res = real_FSAddClientEx(r3, r4, r5); + if(bss.saveFolderChecked == 1) return res; if ((int)bss_ptr != 0x0a000000 && res >= 0) { //int client = client_num_alloc(r3); @@ -118,35 +145,77 @@ DECL(int, FSAddClientEx, void *r3, void *r4, void *r5) { FSAddClient(pClient, FS_RET_NO_ERROR); int client = client_num_alloc(pClient); if(client < MAX_CLIENT && client >= 0) { - cafiine_connect(&bss.socket_fs[client]); + cafiine_connect(&bss.socket_fs[client]); + bss.logsock = bss.socket_fs[client]; }else{ goto error; } // Init command block. FSInitCmdBlock(pCmd); - dump_saves(pClient, pCmd,-1, client); + hook(pClient, pCmd,-1, client); bss.saveFolderChecked = 2; - - - error: - real_FSDelClient(pClient); + + error: real_FSDelClient(pClient); free(pClient); free(pCmd); } } //cafiine_connect(&bss.socket_fs[client]); - //} + //} } + return res; } +static int remove_files_in_dir(void * pClient,void * pCmd, char * path, int handle){ + int ret = 0; + if ((ret = FSOpenDir(pClient, pCmd, path, &handle, FS_RET_ALL_ERROR)) == FS_STATUS_OK){ + char buffer[strlen(path) + 25]; + + __os_snprintf(buffer, sizeof(buffer), "remove files in dir %s",path); + log_string(bss.logsock, buffer, BYTE_LOG_STR); + FSDirEntry dir_entry; + while (FSReadDir(pClient, pCmd, handle, &dir_entry, FS_RET_ALL_ERROR) == FS_STATUS_OK) + { + char full_path[255]; + int i=0; + char *path_ptr = (char *)path; + while(*path_ptr) { + full_path[i++] = *path_ptr++; + } + full_path[i++] = '/'; + char *dir_name_ptr = (char *)dir_entry.name; + while(*dir_name_ptr) { + full_path[i++] = *dir_name_ptr++; + } + full_path[i++] = '\0'; + char buffer[strlen(full_path) + 50]; + __os_snprintf(buffer, sizeof(buffer), "deleting %s",full_path); + log_string(bss.logsock, buffer, BYTE_LOG_STR); + if((ret = FSRemove(pClient,pCmd,full_path,-1)) < 0){ + __os_snprintf(buffer, sizeof(buffer), "error: %d on %s",ret,full_path); + log_string(bss.logsock, buffer, BYTE_LOG_STR); + return -1; + } + } + if((FSCloseDir(pClient, pCmd, handle, FS_RET_NO_ERROR)) <=0 ){ + log_string(bss.logsock, "error while closing dir", BYTE_LOG_STR); + } + } + return 0; +} + +static void hook(void * pClient,void * pCmd, int error, int client){ + log_string(bss.logsock, "hook", BYTE_LOG_STR); + handle_saves(pClient, pCmd,-1, client); +} static void init_Save(){ int (*SAVEInit)(); unsigned int save_handle; OSDynLoad_Acquire("nn_save.rpl", &save_handle); - OSDynLoad_FindExport(save_handle, 0, "SAVEInit", &SAVEInit); + OSDynLoad_FindExport(save_handle, 0, "SAVEInit", (void **)&SAVEInit); SAVEInit(); } @@ -157,10 +226,10 @@ static long getPesistentID(){ void (*nn_Initialize)(void); void (*nn_Finalize)(void); OSDynLoad_Acquire("nn_act.rpl", &nn_act_handle); - OSDynLoad_FindExport(nn_act_handle, 0, "GetPersistentIdEx__Q2_2nn3actFUc", &GetPersistentIdEx); - OSDynLoad_FindExport(nn_act_handle, 0, "GetSlotNo__Q2_2nn3actFv", &GetSlotNo); - OSDynLoad_FindExport(nn_act_handle, 0, "Initialize__Q2_2nn3actFv", &nn_Initialize); - OSDynLoad_FindExport(nn_act_handle, 0, "Finalize__Q2_2nn3actFv", &nn_Finalize); + OSDynLoad_FindExport(nn_act_handle, 0, "GetPersistentIdEx__Q2_2nn3actFUc", (void **)&GetPersistentIdEx); + OSDynLoad_FindExport(nn_act_handle, 0, "GetSlotNo__Q2_2nn3actFv", (void **)&GetSlotNo); + OSDynLoad_FindExport(nn_act_handle, 0, "Initialize__Q2_2nn3actFv", (void **)&nn_Initialize); + OSDynLoad_FindExport(nn_act_handle, 0, "Finalize__Q2_2nn3actFv", (void **)&nn_Finalize); nn_Initialize(); // To be sure that it is really Initialized @@ -183,7 +252,7 @@ static int dump_dir(void *pClient,int client, void *pCmd, char *path, int error, char buffer[strlen(path) + 25]; __os_snprintf(buffer, sizeof(buffer), "open dir %s",path); - log_string(bss.socket_fsa[client], buffer, BYTE_LOG_STR); + log_string(bss.logsock, buffer, BYTE_LOG_STR); FSDirEntry dir_entry; while (FSReadDir(pClient, pCmd, dir_handle, &dir_entry, FS_RET_ALL_ERROR) == FS_STATUS_OK) { @@ -203,14 +272,14 @@ static int dump_dir(void *pClient,int client, void *pCmd, char *path, int error, if((dir_entry.stat.flag&FS_STAT_FLAG_IS_DIRECTORY) == FS_STAT_FLAG_IS_DIRECTORY){ - log_string(bss.socket_fsa[client], "-> dir", BYTE_LOG_STR); + log_string(bss.logsock, "-> dir", BYTE_LOG_STR); dump_dir(pClient,client, pCmd,full_path,-1,my_handle); }else{ //DUMP ret = FSOpenFile(pClient, pCmd, full_path, "r", &my_handle, FS_RET_ALL_ERROR); if (ret >= 0) { __os_snprintf(buffer, sizeof(buffer), "dumping %s",dir_entry.name); - log_string(bss.socket_fsa[client], buffer, BYTE_LOG_STR); + log_string(bss.logsock, buffer, BYTE_LOG_STR); int my_ret = cafiine_send_handle(bss.socket_fsa[client], client, full_path, my_handle); @@ -220,7 +289,7 @@ static int dump_dir(void *pClient,int client, void *pCmd, char *path, int error, int ret2; while ((ret2 = FSReadFile(pClient, pCmd, buffer, 1, size, my_handle, 0, 0)) > 0) cafiine_send_file(bss.socket_fsa[client], buffer, ret2, my_handle); - cafiine_fclose(bss.socket_fsa[client], &ret2, my_handle); + cafiine_fclose(bss.socket_fsa[client], &ret2, my_handle,1); FSSetPosFile(pClient, pCmd, my_handle, 0, FS_RET_ALL_ERROR); free(buffer); FSCloseFile(pClient, pCmd, my_handle, -1); @@ -228,7 +297,7 @@ static int dump_dir(void *pClient,int client, void *pCmd, char *path, int error, char type[2]; type[0] = '9' + ret; type[1] = '\0'; - log_string(bss.socket_fsa[client], type, BYTE_LOG_STR); + log_string(bss.logsock, type, BYTE_LOG_STR); } } @@ -238,22 +307,145 @@ static int dump_dir(void *pClient,int client, void *pCmd, char *path, int error, return 0; } -static void dump_saves(void *pClient, void *pCmd,int error, int client){ +static void handle_saves(void *pClient, void *pCmd,int error, int client){ + log_string(bss.logsock, "handle_saves", BYTE_LOG_STR); init_Save(); long id = getPesistentID(); - log_string(bss.socket_fsa[client], "dumping user savedata", BYTE_LOG_STR); + log_string(bss.logsock, "user savedata", BYTE_LOG_STR); if(id >= 0x80000000 && id <= 0x90000000){ char savepath[20]; - __os_snprintf(savepath, sizeof(savepath), "/vol/save/%08x",id); - dump_dir(pClient,client,pCmd,savepath,-1,50); + int mode; + __os_snprintf(savepath, sizeof(savepath), "/vol/save/%08x",id); + log_string(bss.logsock, "Getting mode!", BYTE_LOG_STR); + if(getMode(bss.socket_fsa[client],&mode)){ + if(mode == BYTE_MODE_D){ + log_string(bss.logsock, "dump mode!", BYTE_LOG_STR); + dump_dir(pClient,client,pCmd,savepath,-1,50); + }else if(mode == BYTE_MODE_I){ + log_string(bss.logsock, "inject mode", BYTE_LOG_STR); + log_string(bss.logsock, "deleting current save", BYTE_LOG_STR); + remove_files_in_dir(pClient,pCmd,savepath,0); + injectFiles(pClient,pCmd,savepath,"/",-1); + log_string(bss.logsock, "flushing quota", BYTE_LOG_STR); + FSFlushQuota(pClient,pCmd,savepath,-1); + } + } + } + /* + log_string(bss.logsock, "dumping common savedata", BYTE_LOG_STR); + dump_dir(pClient,client,pCmd,"/vol/save/common/",error,60); + log_string(bss.logsock, "done!", BYTE_LOG_STR);*/ +} + + +#define BUFFER_SIZE (1024)*100 +void injectFiles(void *pClient, void *pCmd, char * path,char * relativepath, int error){ + + //FSStatus (*FSWriteFileWithPos) (FSClient *pClient, FSCmdBlock *pCmd, const void *source,int size,int count,int fpos,int fileHandle,int flag,FSRetFlag errHandling); + int client = client_num(pClient); + + int type = 0; + log_string(bss.logsock, "injecting files", BYTE_LOG_STR); + char namebuffer[255]; + char logbugger[255]; + int filesize = 0; + + int buf_size = BUFFER_SIZE; + char * pBuffer; + do{ + buf_size -= 0x200; + if(buf_size < 0){ + log_string(bss.logsock, "error on buffer allocation", BYTE_LOG_STR); + return; + } + pBuffer = (char *)MEMAllocFromDefaultHeapEx(buf_size, 0x40); + }while(!pBuffer); + + __os_snprintf(logbugger, sizeof(logbugger), "buffer size: %d bytes",buf_size); + log_string(bss.logsock, logbugger, BYTE_LOG_STR); + + while(getFiles(bss.socket_fsa[client],path,namebuffer, &type,&filesize)){ + if(DEBUG_LOG)log_string(bss.logsock, "got a file", BYTE_LOG_STR); + char newpath[strlen(path) + 1 + strlen(namebuffer)]; + __os_snprintf(newpath, sizeof(newpath), "%s/%s",path,namebuffer); + if(type == BYTE_FILE){ + __os_snprintf(logbugger, sizeof(logbugger), "file: %s%s size: %d",relativepath,namebuffer,filesize); + log_string(bss.logsock, logbugger, BYTE_LOG_STR); + if(DEBUG_LOG) log_string(bss.logsock, "downloading it", BYTE_LOG_STR); + + int handle = 10; + if(FSOpenFile(pClient, pCmd, newpath,"w+",&handle,-1) >= 0){ + if(DEBUG_LOG) log_string(bss.logsock, "file opened and created", BYTE_LOG_STR); + if(filesize > 0){ + int myhandle; + int ret = 0; + if((cafiine_fopen(bss.socket_fsa[client], &ret, newpath, "r", &myhandle)) == 0 && ret == 0){ + if(DEBUG_LOG)__os_snprintf(logbugger, sizeof(logbugger), "cafiine_fopen with handle %d",myhandle); + if(DEBUG_LOG) log_string(bss.logsock, logbugger, BYTE_LOG_STR); + int size = sizeof(char); + int count = buf_size; + int retsize = 0; + int pos = 0; + while(pos < filesize){ + if(DEBUG_LOG) log_string(bss.logsock, "reading", BYTE_LOG_STR); + if(DEBUG_LOG)__os_snprintf(logbugger, sizeof(logbugger), "count %d",count); + if(DEBUG_LOG) log_string(bss.logsock, logbugger, BYTE_LOG_STR); + if(cafiine_fread(bss.socket_fsa[client], &retsize, pBuffer, count, myhandle) == 0){ + __os_snprintf(logbugger, sizeof(logbugger), "got %d",retsize); + if(DEBUG_LOG) log_string(bss.logsock, logbugger, BYTE_LOG_STR); + int fwrite = 0; + if((fwrite = my_FSWriteFile(pClient, pCmd, pBuffer,size,retsize,handle,0,0x0200)) >= 0){ + __os_snprintf(logbugger, sizeof(logbugger), "wrote %d",retsize); + if(DEBUG_LOG) log_string(bss.logsock, logbugger, BYTE_LOG_STR); + }else{ + __os_snprintf(logbugger, sizeof(logbugger), "my_FSWriteFile failed with error: %d",fwrite); + if(DEBUG_LOG) log_string(bss.logsock, logbugger, BYTE_LOG_STR); + log_string(bss.logsock, "error while FSWriteFile", BYTE_LOG_STR); + } + __os_snprintf(logbugger, sizeof(logbugger), "old p %d new p %d",pos,pos+retsize); + if(DEBUG_LOG) log_string(bss.logsock, logbugger, BYTE_LOG_STR); + pos += retsize; + }else{ + log_string(bss.logsock, "error while recieving file", BYTE_LOG_STR); + break; + } + } + + int result = 0; + if((cafiine_fclose(bss.socket_fsa[client], &result, myhandle,0)) == 0 && result == 0){ + if(DEBUG_LOG) log_string(bss.logsock, "cafiine_fclose success", BYTE_LOG_STR); + }else{ + log_string(bss.logsock, "cafiine_fclose failed", BYTE_LOG_STR); + } + - log_string(bss.socket_fsa[client], "dumping common savedata", BYTE_LOG_STR); - dump_dir(pClient,client,pCmd,"/vol/save/common/",error,60); - - log_string(bss.socket_fsa[client], "done!", BYTE_LOG_STR); + }else{ + log_string(bss.logsock, "cafiine_fopen failed", BYTE_LOG_STR); + } + } + + if((FSCloseFile (pClient, pCmd, handle, -1)) <= 0) + log_string(bss.logsock, "FSCloseFile failed", BYTE_LOG_STR); + } + + }else if( type == BYTE_FOLDER){ + __os_snprintf(logbugger, sizeof(logbugger), "dir: %s",namebuffer); + log_string(bss.logsock, logbugger, BYTE_LOG_STR); + if(DEBUG_LOG) log_string(bss.logsock, newpath, BYTE_LOG_STR); + if(FSMakeDir(pClient, pCmd, newpath, -1) == 0){ + char op_offset[strlen(relativepath) + strlen(namebuffer)+ 1 + 1]; + __os_snprintf(op_offset, sizeof(op_offset), "%s%s/",relativepath,namebuffer); + injectFiles(pClient, pCmd, newpath,op_offset,error); + }else{ + log_string(bss.logsock, "folder creation failed", BYTE_LOG_STR); + } + } + } + free(pBuffer); + log_string(bss.logsock, "getting files done", BYTE_LOG_STR); } #define MAKE_MAGIC(x) { x, my_ ## x, &real_ ## x } @@ -270,5 +462,9 @@ struct magic_t { MAKE_MAGIC(FSInit), MAKE_MAGIC(FSShutdown), MAKE_MAGIC(FSAddClientEx), - MAKE_MAGIC(FSDelClient), + MAKE_MAGIC(FSDelClient), + MAKE_MAGIC(FSWriteFile), + MAKE_MAGIC(FSFlushQuota), + + }; diff --git a/saviine/client/main.h b/saviine/client/main.h index 1a86373..a3eec3e 100644 --- a/saviine/client/main.h +++ b/saviine/client/main.h @@ -2,6 +2,31 @@ #include "../common/fs_defs.h" #define NULL ((void *)0) +#define BYTE_NORMAL 0xff +#define BYTE_SPECIAL 0xfe +#define BYTE_OPEN 0x00 +#define BYTE_READ 0x01 +#define BYTE_CLOSE 0x02 +#define BYTE_OK 0x03 +#define BYTE_SETPOS 0x04 +#define BYTE_STATFILE 0x05 +#define BYTE_EOF 0x06 +#define BYTE_GETPOS 0x07 +#define BYTE_REQUEST 0x08 +#define BYTE_REQUEST_SLOW 0x09 +#define BYTE_HANDLE 0x0A +#define BYTE_DUMP 0x0B +#define BYTE_PING 0x0C +#define BYTE_G_MODE 0x0D +#define BYTE_MODE_D 0x0E +#define BYTE_MODE_I 0x0F +#define BYTE_CLOSE_DUMP 0x10 +#define BYTE_LOG_STR 0xfb +#define BYTE_FILE 0xC0 +#define BYTE_FOLDER 0xC1 +#define BYTE_GET_FILES 0xCC +#define BYTE_END 0xfd + void *memcpy(void *dst, const void *src, int bytes); void *memset(void *dst, int val, int bytes); @@ -30,6 +55,8 @@ extern int connect(int socket, void *addr, int addrlen); extern int send(int socket, const void *buffer, int size, int flags); extern int recv(int socket, void *buffer, int size, int flags); extern int __os_snprintf(char* s, int n, const char * format, ...); +int getFiles(int sock, char * path,char * resultname, int * resulttype,int *filesize); +void injectFiles(void *pClient, void *pCmd, char * path,char * relativepath, int error); struct in_addr { unsigned int s_addr; @@ -55,6 +82,7 @@ struct bss_t { char save_path[255]; volatile int saveFolderChecked; volatile int lock; + int logsock; }; #define bss_ptr (*(struct bss_t **)0x100000e4) @@ -62,11 +90,12 @@ struct bss_t { void cafiine_connect(int *socket); void cafiine_disconnect(int socket); +int getMode(int sock, int * result); int cafiine_fopen(int socket, int *result, const char *path, const char *mode, int *handle); int cafiine_send_handle(int sock, int client, const char *path, int handle); void cafiine_send_file(int sock, char *file, int size, int fd); -int cafiine_fread(int socket, int *result, void *buffer, int size, int count, int fd); -int cafiine_fclose(int socket, int *result, int fd); +int cafiine_fread(int socket, int *result, void *buffer, int size, int fd); +int cafiine_fclose(int socket, int *result, int fd, int dumpclose); int cafiine_fsetpos(int socket, int *result, int fd, int set); int cafiine_fgetpos(int socket, int *result, int fd, int *pos); int cafiine_fstat(int sock, int *result, int fd, void *ptr); diff --git a/saviine/client/saviine.c b/saviine/client/saviine.c index 409a643..f862011 100644 --- a/saviine/client/saviine.c +++ b/saviine/client/saviine.c @@ -1,33 +1,22 @@ #include "main.h" static int recvwait(int sock, void *buffer, int len); +static int recvwaitlen(int sock, void *buffer, int len); + static int recvbyte(int sock); static int sendwait(int sock, const void *buffer, int len); - +static int sendbyte(int sock, unsigned char value); static int cafiine_handshake(int sock); #define CHECK_ERROR(cond) if (cond) { goto error; } -#define BYTE_NORMAL 0xff -#define BYTE_SPECIAL 0xfe -//#define BYTE_OPEN 0x00 -//#define BYTE_READ 0x01 -#define BYTE_CLOSE 0x02 -//#define BYTE_OK 0x03 -//#define BYTE_SETPOS 0x04 -//#define BYTE_STATFILE 0x05 -//#define BYTE_EOF 0x06 -//#define BYTE_GETPOS 0x07 -#define BYTE_REQUEST 0x08 -#define BYTE_REQUEST_SLOW 0x09 -#define BYTE_HANDLE 0x0A -#define BYTE_DUMP 0x0B -#define BYTE_PING 0x0C -#define BYTE_LOG_STR 0xfb void GX2WaitForVsync(void); + + + void cafiine_connect(int *psock) { extern unsigned int server_ip; struct sockaddr_in addr; @@ -79,6 +68,56 @@ error: return ret; } +int getMode(int sock,int * result) +{ + while (bss.lock) GX2WaitForVsync(); + bss.lock = 1; + + CHECK_ERROR(sock == -1); + int ret = 0; + + // create and send buffer with : [cmd id][fd][size][buffer data ...] + { + ret = sendbyte(sock, BYTE_G_MODE); + + // wait reply + ret = recvbyte(sock); + CHECK_ERROR(ret < 0); + if(ret == BYTE_MODE_D) *result = BYTE_MODE_D; + if(ret == BYTE_MODE_I) *result = BYTE_MODE_I; + ret = 1; + } +error: + bss.lock = 0; + return ret; +} + + +int cafiine_fsetpos(int sock, int *result, int fd, int set) { + while (bss.lock) GX2WaitForVsync(); + bss.lock = 1; + + CHECK_ERROR(sock == -1); + + int ret; + char buffer[1 + 8]; + buffer[0] = BYTE_SETPOS; + *(int *)(buffer + 1) = fd; + *(int *)(buffer + 5) = set; + ret = sendwait(sock, buffer, 1 + 8); + CHECK_ERROR(ret < 0); + ret = recvbyte(sock); + CHECK_ERROR(ret < 0); + CHECK_ERROR(ret == BYTE_NORMAL); + ret = recvwait(sock, result, 4); + CHECK_ERROR(ret < 0); + + bss.lock = 0; + return 0; +error: + bss.lock = 0; + return -1; +} int cafiine_send_handle(int sock, int client, const char *path, int handle) { @@ -122,6 +161,49 @@ error: bss.lock = 0; return -1; } +int cafiine_fopen(int sock, int *result, const char *path, const char *mode, int *handle) { + while (bss.lock) GX2WaitForVsync(); + bss.lock = 1; + + CHECK_ERROR(sock == -1); + + int final_ret = 0; + int ret; + int len_path = 0; + while (path[len_path++]); + int len_mode = 0; + while (mode[len_mode++]); + + // + { + char buffer[1 + 8 + len_path + len_mode]; + buffer[0] = BYTE_OPEN; + *(int *)(buffer + 1) = len_path; + *(int *)(buffer + 5) = len_mode; + for (ret = 0; ret < len_path; ret++) + buffer[9 + ret] = path[ret]; + for (ret = 0; ret < len_mode; ret++) + buffer[9 + len_path + ret] = mode[ret]; + + ret = sendwait(sock, buffer, 1 + 8 + len_path + len_mode); + } + CHECK_ERROR(ret < 0); + ret = recvbyte(sock); + CHECK_ERROR(ret < 0); + CHECK_ERROR(ret == BYTE_NORMAL); + + ret = recvwait(sock, result, 4); + CHECK_ERROR(ret < 0); + ret = recvwait(sock, handle, 4); + CHECK_ERROR(ret < 0); + +quit: + bss.lock = 0; + return final_ret; +error: + bss.lock = 0; + return -1; +} void cafiine_send_file(int sock, char *file, int size, int fd) { while (bss.lock) GX2WaitForVsync(); @@ -153,10 +235,36 @@ error: bss.lock = 0; return; } +int cafiine_fread(int sock, int *result, void *ptr, int size, int fd) { + while (bss.lock) GX2WaitForVsync(); + bss.lock = 1; + + CHECK_ERROR(sock == -1); + + int ret; + char buffer[1 + 8]; + buffer[0] = BYTE_READ; + *(int *)(buffer + 1) = size; + *(int *)(buffer + 5) = fd; + ret = sendwait(sock, buffer, 1 + 8); + ret = recvbyte(sock); + CHECK_ERROR(ret == BYTE_NORMAL); + int sz; + ret = recvwait(sock, &sz, 4); + + ret = recvwaitlen(sock, ptr, sz); + *result = sz - ret; + ret = sendbyte(sock, BYTE_OK); + + bss.lock = 0; + return 0; +error: + bss.lock = 0; + return -1; +} - -int cafiine_fclose(int sock, int *result, int fd) { +int cafiine_fclose(int sock, int *result, int fd,int dumpclose) { while (bss.lock) GX2WaitForVsync(); bss.lock = 1; @@ -165,11 +273,11 @@ int cafiine_fclose(int sock, int *result, int fd) { int ret; char buffer[1 + 4]; buffer[0] = BYTE_CLOSE; + if(dumpclose)buffer[0] = BYTE_CLOSE_DUMP; *(int *)(buffer + 1) = fd; ret = sendwait(sock, buffer, 1 + 4); CHECK_ERROR(ret < 0); - ret = recvbyte(sock); - CHECK_ERROR(ret < 0); + ret = recvbyte(sock); CHECK_ERROR(ret == BYTE_NORMAL); ret = recvwait(sock, result, 4); CHECK_ERROR(ret < 0); @@ -181,6 +289,55 @@ error: return -1; } +int getFiles(int sock, char * path,char * resultname, int * resulttype, int * filesize){ + while (bss.lock) GX2WaitForVsync(); + bss.lock = 1; + CHECK_ERROR(sock == -1); + int result = 0; + int ret; + // create and send buffer with : [cmd id][len_path][path][filesize] + { + int size = 0; + while (path[size++]); + char buffer[1+4+size]; + + buffer[0] = BYTE_GET_FILES; + *(int *)(buffer + 1) = size; + for (ret = 0; ret < size; ret++) + buffer[5 + ret] = path[ret]; + + // send buffer, wait for reply + ret = sendwait(sock, buffer, 1+4+size); + + // wait reply + ret = recvbyte(sock); + CHECK_ERROR(ret != BYTE_OK); + + ret = recvbyte(sock); + CHECK_ERROR(ret != BYTE_FILE && ret != BYTE_FOLDER); + *resulttype = ret; + size = 0; + ret = recvwait(sock, &size, 4); + CHECK_ERROR(ret < 0); + + ret = recvwait(sock, resultname, size+1); + CHECK_ERROR(ret < 0); + + size = 0; + ret = recvwait(sock, &size, 4); + CHECK_ERROR(ret < 0); + *filesize = size; + ret = recvbyte(sock); + CHECK_ERROR(ret < 0); + CHECK_ERROR(ret != BYTE_SPECIAL); + result = 1; + + } +error: + bss.lock = 0; + return result; +} + void cafiine_send_ping(int sock, int val1, int val2) { while (bss.lock) GX2WaitForVsync(); bss.lock = 1; @@ -211,6 +368,19 @@ static int recvwait(int sock, void *buffer, int len) { error: return ret; } +static int recvwaitlen(int sock, void *buffer, int len) { + int ret; + while (len > 0) { + ret = recv(sock, buffer, len, 0); + CHECK_ERROR(ret < 0); + len -= ret; + buffer += ret; + } + return 0; +error: + return len; +} + static int recvbyte(int sock) { unsigned char buffer[1]; @@ -260,3 +430,9 @@ void log_string(int sock, const char* str, char flag_byte) { bss.lock = 0; } +static int sendbyte(int sock, unsigned char byte) { + unsigned char buffer[1]; + + buffer[0] = byte; + return sendwait(sock, buffer, 1); +} \ No newline at end of file diff --git a/saviine/client/saviine532.ld b/saviine/client/saviine532.ld index d8ac10e..8c39a58 100644 --- a/saviine/client/saviine532.ld +++ b/saviine/client/saviine532.ld @@ -35,7 +35,7 @@ PROVIDE(FSDelClient = 0x1068a08); PROVIDE(FSOpenFile = 0x106ef7c); PROVIDE(FSOpenFileAsync = 0x0106a434); PROVIDE(FSInitCmdBlock = 0x01068c54); - +PROVIDE(FSMakeDir = 0x0106f8e0); PROVIDE(FSCloseFile = 0x106f088); PROVIDE(FSReadFile = 0x106f108); PROVIDE(FSReadFileWithPos = 0x106f194); @@ -43,6 +43,9 @@ PROVIDE(FSGetPosFile = 0x106f4c0); PROVIDE(FSSetPosFile = 0x106f530); PROVIDE(FSGetStatFile = 0x106f5a0); PROVIDE(FSIsEof = 0x106f610); +PROVIDE(FSWriteFile = 0x106F228); +PROVIDE(FSFlushQuota = 0x106FAC8); + /* */ PROVIDE(FSGetStat = 0x0106fdc8); @@ -54,7 +57,7 @@ PROVIDE(FSReadDir = 0x0106f780); PROVIDE(FSCloseDir = 0x0106f700); PROVIDE(FSChangeDir = 0x0106eefc); PROVIDE(FSCloseDir = 0x0106f700); - +PROVIDE(FSRemove = 0x0106F960); /* GX2 methods */ PROVIDE(GX2WaitForVsync = 0x1151964); @@ -65,7 +68,7 @@ PROVIDE(socket = 0x10c21c8); PROVIDE(socketclose = 0x10c2314); PROVIDE(connect = 0x10c0828); PROVIDE(send = 0x10c16ac); -PROVIDE(recv = 0x10c0aec); +PROVIDE(recv = 0x10c0aec); /* Standard library methods */ PROVIDE(memcpy = 0x1035a68); diff --git a/saviine/installer/bin/code532.bin b/saviine/installer/bin/code532.bin index ea31e37..33366d5 100644 Binary files a/saviine/installer/bin/code532.bin and b/saviine/installer/bin/code532.bin differ diff --git a/saviine/installer/bin/saviine.o b/saviine/installer/bin/saviine.o index ac39b32..94ff1df 100644 Binary files a/saviine/installer/bin/saviine.o and b/saviine/installer/bin/saviine.o differ diff --git a/saviine/server/src/Program.cs b/saviine/server/src/Program.cs index 46bdb14..cd09473 100644 --- a/saviine/server/src/Program.cs +++ b/saviine/server/src/Program.cs @@ -13,11 +13,11 @@ namespace saviine_server { public const byte BYTE_NORMAL = 0xff; public const byte BYTE_SPECIAL = 0xfe; - //public const byte BYTE_OPEN = 0x00; - // public const byte BYTE_READ = 0x01; + public const byte BYTE_OPEN = 0x00; + public const byte BYTE_READ = 0x01; public const byte BYTE_CLOSE = 0x02; - //public const byte BYTE_OK = 0x03; - //public const byte BYTE_SETPOS = 0x04; + public const byte BYTE_OK = 0x03; + public const byte BYTE_SETPOS = 0x04; //public const byte BYTE_STATFILE = 0x05; //public const byte BYTE_EOF = 0x06; //public const byte BYTE_GETPOS = 0x07; @@ -26,8 +26,15 @@ namespace saviine_server public const byte BYTE_HANDLE = 0x0A; public const byte BYTE_DUMP = 0x0B; public const byte BYTE_PING = 0x0C; - + public const byte BYTE_G_MODE = 0x0D; + public const byte BYTE_MODE_D = 0x0E; + public const byte BYTE_MODE_I = 0x0F; + public const byte BYTE_CLOSE_DUMP = 0x10; public const byte BYTE_LOG_STR = 0xFB; + public const byte BYTE_FILE = 0xC0; + public const byte BYTE_FOLDER = 0xC1; + public const byte BYTE_GET_FILES = 0xCC; + public const byte BYTE_END = 0xfd; [Flags] public enum FSStatFlag : uint @@ -75,6 +82,7 @@ namespace saviine_server const uint BUFFER_SIZE = 64 * 1024; static Boolean fastmode = false; + static byte op_mode = BYTE_MODE_D; static void Main(string[] args) { if (args.Length > 1) @@ -86,11 +94,36 @@ namespace saviine_server { if (args[0].Equals("fastmode") || args[0].Equals("fast") || args[0].Equals("-fast")) { - fastmode = true; - Console.WriteLine("Now using fastmode"); + op_mode = BYTE_MODE_D; + fastmode = true; + }else if(args[0].Equals("inject")) { + op_mode = BYTE_MODE_I; } } + if (args.Length == 2) + { + if (args[0].Equals("dump")) { + op_mode = BYTE_MODE_D; + if (args[1].Equals("fastmode") || args[1].Equals("fast") || args[1].Equals("-fast")) + { + fastmode = true; + } + }else if(args[0].Equals("inject")) { + op_mode = BYTE_MODE_I; + } + } + + if (op_mode == BYTE_MODE_D) + { + Console.WriteLine("Dump mode"); + if(fastmode)Console.WriteLine("Now using fastmode"); + } + else if(op_mode == BYTE_MODE_I) + { + Console.WriteLine("Injection mode!"); + } + // Check for cafiine_root and logs folder if (!Directory.Exists(root)) { @@ -149,6 +182,21 @@ namespace saviine_server log.Flush(); Console.Write(str); } + public static int countDirectory(string targetDirectory) + { + int x = 0; + // Process the list of files found in the directory. + string [] fileEntries = Directory.GetFiles(targetDirectory); + foreach(string fileName in fileEntries) + x++; + + // Recurse into subdirectories of this directory. + string [] subdirectoryEntries = Directory.GetDirectories(targetDirectory); + foreach(string subdirectory in subdirectoryEntries) + x++; + + return x; + } static void Handle(object client_obj) { @@ -156,6 +204,8 @@ namespace saviine_server FileStream[] files = new FileStream[256]; Dictionary files_request = new Dictionary(); StreamWriter log = null; + Dictionary> dir_files = new Dictionary>(); + try { @@ -196,23 +246,231 @@ namespace saviine_server while (true) { - byte cmd_byte = reader.ReadByte(); + //Log(log, "cmd_byte"); + byte cmd_byte = reader.ReadByte(); switch (cmd_byte) - { - case BYTE_HANDLE: + { + case BYTE_OPEN: { + //Log(log, "BYTE_OPEN"); + bool request_slow = false; + + int len_path = reader.ReadInt32(); + int len_mode = reader.ReadInt32(); + string path = reader.ReadString(Encoding.ASCII, len_path - 1); + if (reader.ReadByte() != 0) throw new InvalidDataException(); + string mode = reader.ReadString(Encoding.ASCII, len_mode - 1); + if (reader.ReadByte() != 0) throw new InvalidDataException(); + + + if (File.Exists(LocalRoot + path)) + { + int handle = -1; + for (int i = 1; i < files.Length; i++) + { + if (files[i] == null) + { + handle = i; + break; + } + } + if (handle == -1) + { + Log(log, name + " Out of file handles!"); + writer.Write(BYTE_SPECIAL); + writer.Write(-19); + writer.Write(0); + break; + } + //Log(log, name + " -> fopen(\"" + path + "\", \"" + mode + "\") = " + handle.ToString()); + + files[handle] = new FileStream(LocalRoot + path, FileMode.Open, FileAccess.Read, FileShare.Read); + + writer.Write(BYTE_SPECIAL); + writer.Write(0); + writer.Write(handle); + + } + else { writer.Write(BYTE_NORMAL); } + + // Log(log, "No request found: " + LocalRoot + path); + + + break; + } + case BYTE_SETPOS: + { + //Log(log, "BYTE_SETPOS"); + int fd = reader.ReadInt32(); + int pos = reader.ReadInt32(); + if ((fd & 0x0fff00ff) == 0x0fff00ff) + { + int handle = (fd >> 8) & 0xff; + if (files[handle] == null) + { + writer.Write(BYTE_SPECIAL); + writer.Write(-38); + break; + } + FileStream f = files[handle]; + Log(log, "Postion was set to " + pos + "for handle " + handle); + f.Position = pos; + writer.Write(BYTE_SPECIAL); + writer.Write(0); + } + else + { + writer.Write(BYTE_NORMAL); + } + break; + } + case BYTE_GET_FILES: + { + int len_path = reader.ReadInt32(); + string path = reader.ReadString(Encoding.ASCII, len_path-1); + if (reader.ReadByte() != 0) throw new InvalidDataException(); + int x = 0; + if (path[0] == '/' && path[1] == '/') + { + path = path.Substring(2); + } + else if (path[0] == '/') + { + path = path.Substring(1); + } + path = LocalRoot + path; + + if(Directory.Exists(path)) { + x = countDirectory(path); + if (x > 0) + { + Dictionary value; + if (!dir_files.TryGetValue(path, out value)) + { + //Console.Write("found no \"" + path + "\" in dic \n"); + value = new Dictionary(); + string[] fileEntries = Directory.GetFiles(path); + foreach (string fn in fileEntries) + { + string fileName = Path.GetFileName(fn); + value.Add(fileName, BYTE_FILE); + } + string[] subdirectoryEntries = Directory.GetDirectories(path); + foreach (string sd in subdirectoryEntries) + { + string subdirectory = Path.GetFileName(sd); + value.Add(subdirectory, BYTE_FOLDER); + } + dir_files.Add(path, value); + //Console.Write("added \"" + path + "\" to dic \n"); + } + else + { + //Console.Write("dic for \"" + path + "\" ready \n"); + } + + if (value.Count > 0) + { + writer.Write(BYTE_OK); + //Console.Write("sent ok byte \n"); + foreach (var item in value) + { //Write + writer.Write(item.Value); + //Console.Write("type : " + item.Value); + writer.Write(item.Key.Length); + //Console.Write("length : " + item.Key.Length); + writer.Write(item.Key, Encoding.ASCII, true); + //Console.Write("filename : " + item.Key); + int length = 0; + if (item.Value == BYTE_FILE) length = (int)new System.IO.FileInfo(path + "/" + item.Key).Length; + writer.Write(length); + //Console.Write("filesize : " + length + " \n"); + value.Remove(item.Key); + //Console.Write("removed from list! " + value.Count + " remaining\n"); + break; + } + writer.Write(BYTE_SPECIAL); // + //Console.Write("file sent, wrote special byte \n"); + } + else + { + writer.Write(BYTE_END); // + //Console.Write("list was empty return BYTE_END \n"); + dir_files.Remove(path); + //Console.Write("removed \"" + path + "\" from dic \n"); + } + } + else + { + //Console.Write(path + "empty \n"); + writer.Write(BYTE_END); // + } + } + else + { + //Console.Write(path + " is not found\n"); + writer.Write(BYTE_END); // + } + //Console.Write("in break \n"); + break; + } + case BYTE_READ: + { + //Log(log,"BYTE_READ"); + int size = reader.ReadInt32(); + int fd = reader.ReadInt32(); + + + FileStream f = files[fd]; + + byte[] buffer = new byte[size]; + int sz = (int)f.Length; + int rd = 0; + + //Log(log, "want size:" + size + " for handle: " + fd); + + writer.Write(BYTE_SPECIAL); + + rd = f.Read(buffer, 0, buffer.Length); + //Log(log,"rd:" + rd); + writer.Write(rd); + writer.Write(buffer, 0, rd); + + int offset = (int)f.Position; + int progress = (int)(((float)offset / (float)sz) * 100); + string strProgress = progress.ToString().PadLeft(3, ' '); + string strSize = (sz / 1024).ToString(); + string strCurrent = (offset / 1024).ToString().PadLeft(strSize.Length, ' '); + Console.Write("\r\t--> {0}% ({1} kB / {2} kB)", strProgress, strCurrent, strSize); + log.Write("\r\t--> {0}% ({1} kB / {2} kB)", strProgress, strCurrent, strSize); + //Console.Write("send " + rd ); + if(offset == sz) Console.Write("\n"); + int ret = -5; + if ((ret =reader.ReadByte()) != BYTE_OK) + { + Console.Write("error, got " + ret + " instead of " + BYTE_OK); + //throw new InvalidDataException(); + } + + //Log(log, "break READ"); + + break; + } + case BYTE_HANDLE: + { + //Log(log,"BYTE_HANDLE"); // Read buffer params : fd, path length, path string int fd = reader.ReadInt32(); int len_path = reader.ReadInt32(); string path = reader.ReadString(Encoding.ASCII, len_path - 1); if (reader.ReadByte() != 0) throw new InvalidDataException(); - if (!Directory.Exists(LocalRoot + path)) + if (!Directory.Exists(LocalRoot + "dump" + path)) { - Directory.CreateDirectory(Path.GetDirectoryName(LocalRoot + path)); + Directory.CreateDirectory(Path.GetDirectoryName(LocalRoot + "dump" + path)); } // Add new file for incoming data - files_request.Add(fd, new FileStream(LocalRoot + path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write)); + files_request.Add(fd, new FileStream(LocalRoot + "dump" + path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write)); // Send response if (fastmode) { writer.Write(BYTE_REQUEST); @@ -227,7 +485,8 @@ namespace saviine_server break; } case BYTE_DUMP: - { + { + //Log(log,"BYTE_DUMP"); // Read buffer params : fd, size, file data int fd = reader.ReadInt32(); int sz = reader.ReadInt32(); @@ -257,25 +516,31 @@ namespace saviine_server } case BYTE_CLOSE: { + //Log(log, "BYTE_CLOSE"); int fd = reader.ReadInt32(); - if ((fd & 0x0fff00ff) == 0x0fff00ff) + + + if (files[fd] == null) { - int handle = (fd >> 8) & 0xff; - if (files[handle] == null) - { - writer.Write(BYTE_SPECIAL); - writer.Write(-38); - break; - } - Log(log, name + " close(" + handle.ToString() + ")"); - FileStream f = files[handle]; - writer.Write(BYTE_SPECIAL); - writer.Write(0); - f.Close(); - files[handle] = null; + writer.Write(-38); + break; } - else + //Log(log, name + " close(" + fd.ToString() + ")"); + FileStream f = files[fd]; + + writer.Write(BYTE_SPECIAL); + writer.Write(0); + f.Close(); + files[fd] = null; + + + break; + } + case BYTE_CLOSE_DUMP: + { + int fd = reader.ReadInt32(); + if ((fd & 0x0fff00ff) != 0x0fff00ff) { // Check if it is a file to dump foreach (var item in files_request) @@ -291,7 +556,6 @@ namespace saviine_server // Close file and remove from request list dump_file.Close(); files_request.Remove(fd); - break; } } @@ -300,18 +564,32 @@ namespace saviine_server writer.Write(BYTE_NORMAL); } break; - } + } case BYTE_PING: { + //Log(log, "BYTE_PING"); int val1 = reader.ReadInt32(); int val2 = reader.ReadInt32(); Log(log, name + " PING RECEIVED with values : " + val1.ToString() + " - " + val2.ToString()); break; } + case BYTE_G_MODE: + { + if (op_mode == BYTE_MODE_D) + { + writer.Write(BYTE_MODE_D); + } + else if (op_mode == BYTE_MODE_I) + { + writer.Write(BYTE_MODE_I); + } + break; + } case BYTE_LOG_STR: { + //Log(log, "BYTE_LOG_STR"); int len_str = reader.ReadInt32(); string str = reader.ReadString(Encoding.ASCII, len_str - 1); if (reader.ReadByte() != 0) throw new InvalidDataException(); @@ -320,6 +598,7 @@ namespace saviine_server break; } default: + Log(log, "xx" + cmd_byte); throw new InvalidDataException(); } } diff --git a/saviine/server/src/bin/dump.bat b/saviine/server/src/bin/dump.bat new file mode 100644 index 0000000..18bad22 --- /dev/null +++ b/saviine/server/src/bin/dump.bat @@ -0,0 +1 @@ +saviine_server.exe dump \ No newline at end of file diff --git a/saviine/server/src/bin/inject.bat b/saviine/server/src/bin/inject.bat new file mode 100644 index 0000000..3b2b394 --- /dev/null +++ b/saviine/server/src/bin/inject.bat @@ -0,0 +1 @@ +saviine_server.exe inject \ No newline at end of file diff --git a/saviine/server/src/bin/saviine_server.exe b/saviine/server/src/bin/saviine_server.exe new file mode 100644 index 0000000..ae95be6 Binary files /dev/null and b/saviine/server/src/bin/saviine_server.exe differ diff --git a/saviine/server/src/saviine_server.v12.suo b/saviine/server/src/saviine_server.v12.suo index 25eba17..4b2cd1e 100644 Binary files a/saviine/server/src/saviine_server.v12.suo and b/saviine/server/src/saviine_server.v12.suo differ