diff --git a/saviine/client/Makefile b/saviine/client/Makefile index c8478fe..cf19cfb 100644 --- a/saviine/client/Makefile +++ b/saviine/client/Makefile @@ -24,7 +24,7 @@ SFLAGS := -mgekko -mregnames # -memb: enable embedded application specific compilation # -ffunction-sections: split up functions so linker can garbage collect # -fdata-sections: split up data so linker can garbage collect -CFLAGS := -O2 -Wall -x c -std=gnu99 \ +CFLAGS := -O0 -Wall -x c -std=gnu99 \ -ffreestanding \ -mrvl -mcpu=750 -meabi -mhard-float -fshort-wchar \ -msdata=none -memb -ffunction-sections -fdata-sections \ diff --git a/saviine/client/main.c b/saviine/client/main.c index 0f3291c..1ac22da 100644 --- a/saviine/client/main.c +++ b/saviine/client/main.c @@ -5,20 +5,8 @@ res (* real_ ## name)(__VA_ARGS__) __attribute__((section(".magicptr"))); \ res my_ ## name(__VA_ARGS__) #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); -extern FSStatus FSCloseDir(FSClient *pClient, FSCmdBlock *pCmd, int dh, FSRetFlag errHandling); -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 handle_saves(void *pClient, void *pCmd,int error, int client); -static void hook(void * pClient,void * pCmd, int error, int client); +#define BUFFER_SIZE (1024)*100*2 +#define BUFFER_SIZE_STEPS 0x200 DECL(int, FSAInit, void) { if ((int)bss_ptr == 0x0a000000) { @@ -56,24 +44,6 @@ static int strlen(char* path) { 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; @@ -153,7 +123,7 @@ DECL(int, FSAddClientEx, void *r3, void *r4, void *r5) { // Init command block. FSInitCmdBlock(pCmd); - hook(pClient, pCmd,-1, client); + hook(pClient, pCmd,-1); bss.saveFolderChecked = 2; error: real_FSDelClient(pClient); @@ -168,333 +138,259 @@ DECL(int, FSAddClientEx, void *r3, void *r4, void *r5) { 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){ +void hook(void * pClient,void * pCmd, int error){ log_string(bss.logsock, "hook", BYTE_LOG_STR); - handle_saves(pClient, pCmd,-1, client); + handle_saves(pClient, pCmd,-1); } -static void init_Save(){ - int (*SAVEInit)(); - unsigned int save_handle; - OSDynLoad_Acquire("nn_save.rpl", &save_handle); - OSDynLoad_FindExport(save_handle, 0, "SAVEInit", (void **)&SAVEInit); - SAVEInit(); -} - -static long getPesistentID(){ - unsigned int nn_act_handle; - unsigned long (*GetPersistentIdEx)(unsigned char); - int (*GetSlotNo)(void); - 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", (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 - - unsigned char slotno = GetSlotNo(); - long idlong = GetPersistentIdEx(slotno); - - - nn_Finalize(); //must be called an equal number of times to nn_Initialize - return idlong; -} - -#define DUMP_BLOCK_SIZE (0x200 * 100) -#define DUMP_BLOCK_SIZE_SLOW (0x20 * 100) -static int dump_dir(void *pClient,int client, void *pCmd, char *path, int error, int handle){ - int dir_handle = handle; - int my_handle = handle +1; - int ret = 0; - if ((ret = FSOpenDir(pClient, pCmd, path, &dir_handle, FS_RET_ALL_ERROR)) == FS_STATUS_OK) - { - char buffer[strlen(path) + 25]; - - __os_snprintf(buffer, sizeof(buffer), "open dir %s",path); - 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) - { - 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'; - - - - if((dir_entry.stat.flag&FS_STAT_FLAG_IS_DIRECTORY) == FS_STAT_FLAG_IS_DIRECTORY){ - 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.logsock, buffer, BYTE_LOG_STR); - int my_ret = cafiine_send_handle(bss.socket_fsa[client], client, full_path, my_handle); - - - - int size = (my_ret == 1 ? DUMP_BLOCK_SIZE : DUMP_BLOCK_SIZE_SLOW); - void * buffer = memalign(sizeof(char) * size, 0x40); - 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,1); - FSSetPosFile(pClient, pCmd, my_handle, 0, FS_RET_ALL_ERROR); - free(buffer); - FSCloseFile(pClient, pCmd, my_handle, -1); - }else{ - char type[2]; - type[0] = '9' + ret; - type[1] = '\0'; - log_string(bss.logsock, type, BYTE_LOG_STR); - } - } - - } - FSCloseDir(pClient, pCmd, dir_handle, FS_RET_NO_ERROR); - } - return 0; -} -#define BUFFER_SIZE (1024)*100 -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(); +void handle_saves(void *pClient, void *pCmd,int error){ + log_string(bss.logsock, "init", BYTE_LOG_STR); + int client = client_num(pClient); + unsigned char slotNo; + long id = getPesistentID(&slotNo); + init_Save(slotNo); int mode; - log_string(bss.logsock, "user savedata", BYTE_LOG_STR); + + log_string(bss.logsock, "getting mode", BYTE_LOG_STR); if(getMode(bss.socket_fsa[client],&mode)){ if(id >= 0x80000000 && id <= 0x90000000){ - char savepath[20]; - + char savepath[20]; __os_snprintf(savepath, sizeof(savepath), "/vol/save/%08x",id); - log_string(bss.logsock, "Getting mode!", BYTE_LOG_STR); - { - 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); - int buf_size = BUFFER_SIZE; - char * pBuffer; - int failed = 0; - do{ - buf_size -= 0x200; - if(buf_size < 0){ - log_string(bss.logsock, "error on buffer allocation", BYTE_LOG_STR); - failed = 1; - break; - } - pBuffer = (char *)MEMAllocFromDefaultHeapEx(buf_size, 0x40); - }while(!pBuffer); - if(!failed){ - int result = injectFiles(pClient,pCmd,savepath,"/",pBuffer,buf_size,-1); - if(result == -1){ - log_string(bss.logsock, "injection failed, trying to restore the data", BYTE_LOG_STR); - //TODO FSRollbackQuota - }else{ - char logbugger[50]; - __os_snprintf(logbugger, sizeof(logbugger), "injected %d files, flushing the data now",result); - log_string(bss.logsock, logbugger, BYTE_LOG_STR); - if(FSFlushQuota(pClient,pCmd,savepath,-1) == 0){ - log_string(bss.logsock, "success", BYTE_LOG_STR); - }else{ - log_string(bss.logsock, "failed", BYTE_LOG_STR); - } - } - } - - } + if(mode == BYTE_MODE_D){ + log_string(bss.logsock, "dump mode!", BYTE_LOG_STR); + dumpSavaData(pClient, pCmd,id,error); + }else if(mode == BYTE_MODE_I){ + log_string(bss.logsock, "inject mode", BYTE_LOG_STR); + injectSaveData(pClient,pCmd,id,error); } - + } + } +} + +void dumpSavaData(void *pClient, void *pCmd,long persistentID,int error){ + int client = client_num(pClient); + /* + Allocate buffer for injection + */ + int buf_size = BUFFER_SIZE; + char * pBuffer; + int failed = 0; + do{ + buf_size -= BUFFER_SIZE_STEPS; + if(buf_size < 0){ + log_string(bss.logsock, "error on buffer allocation", BYTE_LOG_STR); + failed = 1; + break; } - if(mode == BYTE_MODE_D){ - 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); - }else{ - log_string(bss.logsock, "common injection", BYTE_LOG_STR); - int buf_size = BUFFER_SIZE; - char * pBuffer; - int failed = 0; - do{ - buf_size -= 0x200; - if(buf_size < 0){ - log_string(bss.logsock, "error on buffer allocation", BYTE_LOG_STR); + pBuffer = (char *)MEMAllocFromDefaultHeapEx(buf_size, 0x40); + }while(!pBuffer); + + if(!failed){ + int mask = 0; + char buffer[60]; + __os_snprintf(buffer, sizeof(buffer), "allocated %d bytes",buf_size); + log_string(bss.logsock, buffer, BYTE_LOG_STR); + if(saviine_start_dump(bss.socket_fsa[client], persistentID,&mask)){ + if((mask & MASK_USER) == MASK_USER){ + char savepath[20]; + __os_snprintf(savepath, sizeof(savepath), "/vol/save/%08x",persistentID); + log_string(bss.logsock, "user savedata", BYTE_LOG_STR); + if(dump_dir(pClient,pCmd,savepath,pBuffer,buf_size,-1,50) == -1){ + log_string(bss.logsock, "error dumping user dir", BYTE_LOG_STR); failed = 1; - break; - } - pBuffer = (char *)MEMAllocFromDefaultHeapEx(buf_size, 0x40); - }while(!pBuffer); - if(!failed){ - int result = injectFiles(pClient,pCmd,"/vol/save/common/","/",pBuffer,buf_size,-1); - if(result == -1){ - log_string(bss.logsock, "injection failed, trying to restore the data", BYTE_LOG_STR); - //TODO FSRollbackQuota - }else{ - char logbugger[50]; - __os_snprintf(logbugger, sizeof(logbugger), "injected %d files, flushing the data now",result); - log_string(bss.logsock, logbugger, BYTE_LOG_STR); - if(FSFlushQuota(pClient,pCmd,"/vol/save/common/",-1) == 0){ - log_string(bss.logsock, "success", BYTE_LOG_STR); - }else{ - log_string(bss.logsock, "failed", BYTE_LOG_STR); - } } } + if((mask & MASK_COMMON) == MASK_COMMON && !failed){ + char * commonDir = "/vol/save/common"; + log_string(bss.logsock, "dumping common savedata", BYTE_LOG_STR); + if(dump_dir(pClient,pCmd,commonDir,pBuffer,buf_size,error,60) == -1){ + log_string(bss.logsock, "error dumping common dir (maybe the game has no common folder?)", BYTE_LOG_STR); + } + } + log_string(bss.logsock, "done!", BYTE_LOG_STR); + + if(!saviine_end_dump(bss.socket_fsa[client])) if(DEBUG_LOG) log_string(bss.logsock, "saviine_end_injection() failed", BYTE_LOG_STR); + free(pBuffer); + if(DEBUG_LOG) log_string(bss.logsock, "end of dump", BYTE_LOG_STR); + }else{ + log_string(bss.logsock, "saviine_start_dump() failed", BYTE_LOG_STR); } } } +int dump_dir(void *pClient, void *pCmd, char *path, void * pBuffer, int size,int error, int handle){ + int client = client_num(pClient); + int dir_handle = handle; + int my_handle = handle +1; + int ret = 0; + int final_result = 0; + if ((ret = FSOpenDir(pClient, pCmd, path, &dir_handle, FS_RET_ALL_ERROR)) == FS_STATUS_OK){ + char buffer[strlen(path) + 25]; + __os_snprintf(buffer, sizeof(buffer), "open dir %s",path); + 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 && final_result == 0) + { + char full_path[strlen(path) + 1 + strlen(dir_entry.name) +1]; + __os_snprintf(full_path, sizeof(full_path), "%s/%s",path,dir_entry.name); + + if((dir_entry.stat.flag&FS_STAT_FLAG_IS_DIRECTORY) == FS_STAT_FLAG_IS_DIRECTORY){ + log_string(bss.logsock, "-> dir", BYTE_LOG_STR); + if(dump_dir(pClient, pCmd,full_path,pBuffer,size,-1,my_handle) == -1){ + log_string(bss.logsock, "error", BYTE_LOG_STR); + final_result = -1; + } + }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.logsock, buffer, BYTE_LOG_STR); + + int buf_size = BUFFER_SIZE; + int ret2; + + int my_ret = cafiine_send_handle(bss.socket_fsa[client], client, full_path, my_handle); + if(my_ret != -1){ + while ((ret2 = FSReadFile(pClient, pCmd, pBuffer, 1, buf_size, my_handle, 0, 0)) > 0) + cafiine_send_file(bss.socket_fsa[client], pBuffer, ret2, my_handle); + cafiine_fclose(bss.socket_fsa[client], &ret2, my_handle,1); + }else{ + log_string(bss.logsock, "error on opening file on pc" , BYTE_LOG_STR); + final_result = -1; + } + + FSSetPosFile(pClient, pCmd, my_handle, 0, FS_RET_ALL_ERROR); + FSCloseFile(pClient, pCmd, my_handle, -1); + }else{ + char buffer[100]; + __os_snprintf(buffer, sizeof(buffer), "error on FSOpenFile: %d",ret); + log_string(bss.logsock, buffer, BYTE_LOG_STR); + final_result = -1; + } + } + } + FSCloseDir(pClient, pCmd, dir_handle, FS_RET_NO_ERROR); + }else{ + log_string(bss.logsock, "error on FSOpenDir()", BYTE_LOG_STR); + final_result = -1; + } + return final_result; +} + +/************************** + Injection functions +**************************/ +void injectSaveData(void *pClient, void *pCmd,long persistentID,int error){ + int client = client_num(pClient); + char logbuffer[255]; + /* + Allocate buffer for injection + */ + int buf_size = BUFFER_SIZE; + char * pBuffer; + int failed = 0; + do{ + buf_size -= BUFFER_SIZE_STEPS; + if(buf_size < 0){ + log_string(bss.logsock, "error on buffer allocation", BYTE_LOG_STR); + failed = 1; + break; + } + pBuffer = (char *)MEMAllocFromDefaultHeapEx(buf_size, 0x40); + }while(!pBuffer); + + if(!failed){ + int result = 0; + int mask = 0; + if((result = saviine_start_injection(bss.socket_fsa[client], persistentID,&mask))){ + if((mask & MASK_USER) == MASK_USER){ + char savepath[20]; + __os_snprintf(savepath, sizeof(savepath), "/vol/save/%08x",persistentID); + __os_snprintf(logbuffer, sizeof(logbuffer), "injecting new userdata in %08x",persistentID); + log_string(bss.logsock, logbuffer, BYTE_LOG_STR); + log_string(bss.logsock, "deleting userdata save", BYTE_LOG_STR); + if(remove_files_in_dir(pClient,pCmd,savepath,0) == -1){ + failed = 1; + }else{ + /* + Inject Save + */ + result = injectFiles(pClient,pCmd,savepath,"/",pBuffer,buf_size,-1); + doFlushOrRollback(pClient,pCmd,result,savepath); + } + } + if((mask & MASK_COMMON) == MASK_COMMON && !failed){ + char * commonDir = "/vol/save/common"; + + if((mask & MASK_COMMON_CLEAN) == MASK_COMMON_CLEAN){ + log_string(bss.logsock, "deleting common save", BYTE_LOG_STR); + if(remove_files_in_dir(pClient,pCmd,commonDir,0) == -1){ + failed = 1; + } + } + if(!failed){ + /* + Inject common + */ + result = injectFiles(pClient,pCmd,commonDir,"/",pBuffer,buf_size,-1); + doFlushOrRollback(pClient,pCmd,result,commonDir); + } + } + if(!saviine_end_injection(bss.socket_fsa[client])) if(DEBUG_LOG) log_string(bss.logsock, "saviine_end_injection() failed", BYTE_LOG_STR); + free(pBuffer); + if(DEBUG_LOG)log_string(bss.logsock, "end of injection", BYTE_LOG_STR); + }else{ + log_string(bss.logsock, "saviine_start_injection() failed", BYTE_LOG_STR); + } + } +} int injectFiles(void *pClient, void *pCmd, char * path,char * relativepath,char * pBuffer, int buffer_size, 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 failed = 0; int filesinjected = 0; int type = 0; log_string(bss.logsock, "injecting files", BYTE_LOG_STR); char namebuffer[255]; - char logbugger[255]; + char logbuffer[255]; int filesize = 0; - - if(!failed){ - __os_snprintf(logbugger, sizeof(logbugger), "buffer size: %d bytes",buffer_size); - log_string(bss.logsock, logbugger, BYTE_LOG_STR); + __os_snprintf(logbuffer, sizeof(logbuffer), "buffer size: %d bytes",buffer_size); + log_string(bss.logsock, logbuffer, BYTE_LOG_STR); - while(getFiles(bss.socket_fsa[client],path,namebuffer, &type,&filesize) && !failed){ - + while(saviine_readdir(bss.socket_fsa[client],path,namebuffer, &type,&filesize) && !failed){ 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); + __os_snprintf(logbuffer, sizeof(logbuffer), "file: %s%s size: %d",relativepath,namebuffer,filesize); + log_string(bss.logsock, logbuffer, 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 = buffer_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); - failed = 1; - } - __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); - failed = 1; - 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); - failed = 1; - } - - }else{ - log_string(bss.logsock, "cafiine_fopen failed", BYTE_LOG_STR); - failed = 1; - } + if(filesize > 0){ + failed = doInjectForFile(pClient,pCmd,handle,newpath,filesize,pBuffer,buffer_size); + }else{ + if(DEBUG_LOG) log_string(bss.logsock, "filesize is 0", BYTE_LOG_STR); } if((FSCloseFile (pClient, pCmd, handle, -1)) < 0){ log_string(bss.logsock, "FSCloseFile failed", BYTE_LOG_STR); failed = 1; - } - + } }else{ log_string(bss.logsock, "opening the file failed", BYTE_LOG_STR); failed = 1; } if(!failed) filesinjected++; }else if( type == BYTE_FOLDER){ - __os_snprintf(logbugger, sizeof(logbugger), "dir: %s",namebuffer); - log_string(bss.logsock, logbugger, BYTE_LOG_STR); + __os_snprintf(logbuffer, sizeof(logbuffer), "dir: %s",namebuffer); + log_string(bss.logsock, logbuffer, 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]; @@ -510,14 +406,163 @@ int injectFiles(void *pClient, void *pCmd, char * path,char * relativepath,char failed = 1; } } - } - free(pBuffer); + } if(failed) return -1; else return filesinjected; }else{ return -1; + } +} + +int doInjectForFile(void * pClient, void * pCmd,int handle,char * filepath,int filesize,void * pBuffer,int buf_size){ + int client = client_num(pClient); + int failed = 0; + int myhandle; + int ret = 0; + char logbuffer[255]; + if((cafiine_fopen(bss.socket_fsa[client], &ret, filepath, "r", &myhandle)) == 0 && ret == 0){ + if(DEBUG_LOG)__os_snprintf(logbuffer, sizeof(logbuffer), "cafiine_fopen with handle %d",myhandle); + if(DEBUG_LOG) log_string(bss.logsock, logbuffer, BYTE_LOG_STR); + int retsize = 0; + int pos = 0; + while(pos < filesize){ + if(DEBUG_LOG) log_string(bss.logsock, "reading", BYTE_LOG_STR); + if(cafiine_fread(bss.socket_fsa[client], &retsize, pBuffer, buf_size , myhandle) == 0){ + if(DEBUG_LOG)__os_snprintf(logbuffer, sizeof(logbuffer), "got %d",retsize); + if(DEBUG_LOG) log_string(bss.logsock, logbuffer, BYTE_LOG_STR); + int fwrite = 0; + if((fwrite = my_FSWriteFile(pClient, pCmd, pBuffer,sizeof(char),retsize,handle,0,0x0200)) >= 0){ + if(DEBUG_LOG)__os_snprintf(logbuffer, sizeof(logbuffer), "wrote %d",retsize); + if(DEBUG_LOG) log_string(bss.logsock, logbuffer, BYTE_LOG_STR); + }else{ + if(DEBUG_LOG)__os_snprintf(logbuffer, sizeof(logbuffer), "my_FSWriteFile failed with error: %d",fwrite); + if(DEBUG_LOG) log_string(bss.logsock, logbuffer, BYTE_LOG_STR); + log_string(bss.logsock, "error while FSWriteFile", BYTE_LOG_STR); + failed = 1; + } + if(DEBUG_LOG)__os_snprintf(logbuffer, sizeof(logbuffer), "old p %d new p %d",pos,pos+retsize); + if(DEBUG_LOG) log_string(bss.logsock, logbuffer, BYTE_LOG_STR); + pos += retsize; + }else{ + log_string(bss.logsock, "error while recieving file", BYTE_LOG_STR); + failed = 1; + 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); + failed = 1; + } + + + }else{ + log_string(bss.logsock, "cafiine_fopen failed", BYTE_LOG_STR); + failed = 1; } + return failed; +} + +/************************* + Util functions +**************************/ + +/*flush if result != -1*/ +void doFlushOrRollback(void *pClient, void *pCmd,int result,char *savepath){ + char logbuffer[50 + strlen(savepath)]; + if(result != -1){ + __os_snprintf(logbuffer, sizeof(logbuffer), "injected %d files",result); + log_string(bss.logsock, logbuffer, BYTE_LOG_STR); + log_string(bss.logsock, "Flushing data now", BYTE_LOG_STR); + if(FSFlushQuota(pClient,pCmd,savepath,-1) == 0){ + log_string(bss.logsock, "success", BYTE_LOG_STR); + }else{ + log_string(bss.logsock, "failed", BYTE_LOG_STR); + } + }else{ + log_string(bss.logsock, "injection failed, trying to restore the data", BYTE_LOG_STR); + if(FSRollbackQuota(pClient,pCmd,savepath,-1) == 0){ + log_string(bss.logsock, "rollback done", BYTE_LOG_STR); + }else{ + log_string(bss.logsock, "rollback failed", BYTE_LOG_STR); + } + } +} + +void init_Save(unsigned char slotNo){ + int (*SAVEInit)(); + int (*SAVEInitSaveDir)(unsigned char accountSlotNo); + unsigned int save_handle; + OSDynLoad_Acquire("nn_save.rpl", &save_handle); + OSDynLoad_FindExport(save_handle, 0, "SAVEInit", (void **)&SAVEInit); + OSDynLoad_FindExport(save_handle, 0, "SAVEInitSaveDir", (void **)&SAVEInitSaveDir); + + SAVEInit(); + SAVEInitSaveDir(slotNo); + SAVEInitSaveDir(255U); +} + +long getPesistentID(unsigned char * slotno){ + unsigned int nn_act_handle; + unsigned long (*GetPersistentIdEx)(unsigned char); + int (*GetSlotNo)(void); + 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", (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 + + *slotno = GetSlotNo(); + + long idlong = GetPersistentIdEx(*slotno); + + nn_Finalize(); //must be called an equal number of times to nn_Initialize + return idlong; +} + +int remove_files_in_dir(void * pClient,void * pCmd, char * path, int handle){ + int ret = 0; + int my_handle = handle +1; + char buffer[strlen(path) + 50]; + if ((ret = FSOpenDir(pClient, pCmd, path, &handle, FS_RET_ALL_ERROR)) == FS_STATUS_OK){ + __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[strlen(path) + 1 + strlen(dir_entry.name) +1]; + __os_snprintf(full_path, sizeof(full_path), "%s/%s",path,dir_entry.name); + if((dir_entry.stat.flag&FS_STAT_FLAG_IS_DIRECTORY) == FS_STAT_FLAG_IS_DIRECTORY){ + log_string(bss.logsock, "recursive deletion", BYTE_LOG_STR); + if(remove_files_in_dir(pClient,pCmd,full_path,my_handle) == -1) return -1; + }else{ + 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 removing %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 -1; + } + }else{ + __os_snprintf(buffer, sizeof(buffer), "error: %d on opening %s",ret,path); + log_string(bss.logsock, buffer, BYTE_LOG_STR); + return -1; + } + return 0; } #define MAKE_MAGIC(x) { x, my_ ## x, &real_ ## x } @@ -537,6 +582,4 @@ struct magic_t { MAKE_MAGIC(FSDelClient), MAKE_MAGIC(FSWriteFile), MAKE_MAGIC(FSFlushQuota), - - }; diff --git a/saviine/client/main.h b/saviine/client/main.h index e6e35d8..3332d63 100644 --- a/saviine/client/main.h +++ b/saviine/client/main.h @@ -24,9 +24,18 @@ #define BYTE_LOG_STR 0xfb #define BYTE_FILE 0xC0 #define BYTE_FOLDER 0xC1 -#define BYTE_GET_FILES 0xCC +#define BYTE_READ_DIR 0xCC +#define BYTE_INJECTSTART 0x40 +#define BYTE_INJECTEND 0x41 +#define BYTE_DUMPSTART 0x42 +#define BYTE_DUMPEND 0x43 #define BYTE_END 0xfd +#define MASK_NORMAL 0x8000 +#define MASK_USER 0x0100 +#define MASK_COMMON 0x0200 +#define MASK_COMMON_CLEAN 0x0400 + void *memcpy(void *dst, const void *src, int bytes); void *memset(void *dst, int val, int bytes); @@ -47,16 +56,40 @@ extern FSStatus FSAddClient(FSClient *pClient, FSRetFlag errHandling); extern void FSInitCmdBlock(FSCmdBlock *pCmd); extern FSStatus FSCloseDir(FSClient *pClient, FSCmdBlock *pCmd, int dh, FSRetFlag errHandling); extern FSStatus FSOpenFile(FSClient *pClient, FSCmdBlock *pCmd, char *path,char *mode,int *dh,FSRetFlag errHandling); - +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); +extern FSStatus FSCloseDir(FSClient *pClient, FSCmdBlock *pCmd, int dh, FSRetFlag errHandling); +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 FSStatus FSRollbackQuota(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); + extern void socket_lib_init(); extern int socket(int domain, int type, int protocol); extern int socketclose(int socket); 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); + +int saviine_readdir(int sock, char * path,char * resultname, int * resulttype,int *filesize); int injectFiles(void *pClient, void *pCmd, char * path,char * relativepath,char * pBuffer, int buffer_size, int error); +void doFlushOrRollback(void *pClient,void *pCmd,int result,char *savepath); +void injectSaveData(void *pClient, void *pCmd,long persistentID,int error); +void dumpSavaData(void *pClient, void *pCmd,long persistentID,int error); +long getPesistentID(unsigned char * slotno); +void init_Save(unsigned char slotNo); +int doInjectForFile(void * pClient, void * pCmd,int handle,char * filepath,int filesize,void * pBuffer,int buf_size); +void handle_saves(void *pClient, void *pCmd,int error); +void hook(void * pClient,void * pCmd, int error); +int dump_dir(void *pClient, void *pCmd, char *path, void * pBuffer, int size,int error, int handle); +int remove_files_in_dir(void * pClient,void * pCmd, char * path, int handle); struct in_addr { unsigned int s_addr; @@ -101,4 +134,9 @@ int cafiine_fgetpos(int socket, int *result, int fd, int *pos); int cafiine_fstat(int sock, int *result, int fd, void *ptr); int cafiine_feof(int sock, int *result, int fd); void cafiine_send_ping(int sock, int val1, int val2); -void log_string(int sock, const char* str, char flag_byte); \ No newline at end of file +void log_string(int sock, const char* str, char flag_byte); + +int saviine_end_injection(int sock); +int saviine_start_injection(int sock, long persistentID,int * mask); +int saviine_start_dump(int sock, long persistentID,int * mask); +int saviine_end_dump(int sock); \ No newline at end of file diff --git a/saviine/client/saviine.c b/saviine/client/saviine.c index f862011..1413ff9 100644 --- a/saviine/client/saviine.c +++ b/saviine/client/saviine.c @@ -72,9 +72,8 @@ int getMode(int sock,int * result) { while (bss.lock) GX2WaitForVsync(); bss.lock = 1; - - CHECK_ERROR(sock == -1); int ret = 0; + CHECK_ERROR(sock == -1); // create and send buffer with : [cmd id][fd][size][buffer data ...] { @@ -145,6 +144,8 @@ int cafiine_send_handle(int sock, int client, const char *path, int handle) // wait reply ret = recvbyte(sock); + CHECK_ERROR(ret < 0); + CHECK_ERROR(ret == BYTE_SPECIAL); if(ret == BYTE_REQUEST){ ret = 1; }else{ @@ -152,6 +153,7 @@ int cafiine_send_handle(int sock, int client, const char *path, int handle) } // wait reply int special_ret = recvbyte(sock); + CHECK_ERROR(special_ret < 0); CHECK_ERROR(special_ret != BYTE_SPECIAL); bss.lock = 0; return ret; @@ -164,10 +166,9 @@ error: int cafiine_fopen(int sock, int *result, const char *path, const char *mode, int *handle) { while (bss.lock) GX2WaitForVsync(); bss.lock = 1; - + int final_result = -1; CHECK_ERROR(sock == -1); - int final_ret = 0; int ret; int len_path = 0; while (path[len_path++]); @@ -186,23 +187,23 @@ int cafiine_fopen(int sock, int *result, const char *path, const char *mode, int 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); + 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); + ret = recvwait(sock, result, 4); + CHECK_ERROR(ret < 0); + ret = recvwait(sock, handle, 4); + CHECK_ERROR(ret < 0); + } + final_result = 0; + -quit: - bss.lock = 0; - return final_ret; error: bss.lock = 0; - return -1; + return final_result; } void cafiine_send_file(int sock, char *file, int size, int fd) { @@ -225,7 +226,7 @@ void cafiine_send_file(int sock, char *file, int size, int fd) { // send buffer, wait for reply ret = sendwait(sock, buffer, 1 + 4 + 4 + size); - + CHECK_ERROR(ret < 0); // wait reply ret = recvbyte(sock); CHECK_ERROR(ret != BYTE_SPECIAL); @@ -246,16 +247,18 @@ int cafiine_fread(int sock, int *result, void *ptr, int size, int fd) { buffer[0] = BYTE_READ; *(int *)(buffer + 1) = size; *(int *)(buffer + 5) = fd; - ret = sendwait(sock, buffer, 1 + 8); + ret = sendwait(sock, buffer, 1 + 8); + CHECK_ERROR(ret < 0); ret = recvbyte(sock); CHECK_ERROR(ret == BYTE_NORMAL); int sz; ret = recvwait(sock, &sz, 4); - + CHECK_ERROR(ret < 0); ret = recvwaitlen(sock, ptr, sz); *result = sz - ret; ret = sendbyte(sock, BYTE_OK); - + CHECK_ERROR(ret < 0); + bss.lock = 0; return 0; error: @@ -289,11 +292,115 @@ error: return -1; } -int getFiles(int sock, char * path,char * resultname, int * resulttype, int * filesize){ +int saviine_start_injection(int sock, long persistentID,int * mask){ while (bss.lock) GX2WaitForVsync(); bss.lock = 1; - CHECK_ERROR(sock == -1); int result = 0; + CHECK_ERROR(sock == -1); + int ret; + { + char buffer[1+4]; + + buffer[0] = BYTE_INJECTSTART; + *(long *)(buffer + 1) = persistentID; + ret = sendwait(sock, buffer, 1 + 4); + CHECK_ERROR(ret < 0); + + ret = recvbyte(sock); + CHECK_ERROR(ret < 0); + CHECK_ERROR(ret != BYTE_SPECIAL); + + ret = recvwait(sock, mask, 4); + CHECK_ERROR(ret < 0); + CHECK_ERROR((*mask & MASK_NORMAL) != MASK_NORMAL); + + ret = recvbyte(sock); + CHECK_ERROR(ret < 0); + CHECK_ERROR(ret != BYTE_SPECIAL); + result = 1; + } +error: + bss.lock = 0; + return result; +} + +int saviine_end_injection(int sock){ + while (bss.lock) GX2WaitForVsync(); + bss.lock = 1; + int result = 0; + CHECK_ERROR(sock == -1); + int ret; + { + ret = sendbyte(sock, BYTE_INJECTEND); + CHECK_ERROR(ret < 0); + + ret = recvbyte(sock); + CHECK_ERROR(ret < 0); + CHECK_ERROR(ret != BYTE_OK); + result = 1; + } +error: + bss.lock = 0; + return result; +} + +int saviine_start_dump(int sock, long persistentID,int * mask){ + while (bss.lock) GX2WaitForVsync(); + bss.lock = 1; + int result = 0; + CHECK_ERROR(sock == -1); + int ret; + { + char buffer[1+4]; + + buffer[0] = BYTE_DUMPSTART; + *(long *)(buffer + 1) = persistentID; + ret = sendwait(sock, buffer, 1 + 4); + CHECK_ERROR(ret < 0); + + ret = recvbyte(sock); + CHECK_ERROR(ret < 0); + CHECK_ERROR(ret != BYTE_SPECIAL); + + ret = recvwait(sock, mask, 4); + CHECK_ERROR(ret < 0); + CHECK_ERROR((*mask & MASK_NORMAL) != MASK_NORMAL); + + ret = recvbyte(sock); + CHECK_ERROR(ret < 0); + CHECK_ERROR(ret != BYTE_SPECIAL); + result = 1; + } +error: + bss.lock = 0; + return result; +} + +int saviine_end_dump(int sock){ + while (bss.lock) GX2WaitForVsync(); + bss.lock = 1; + int result = 0; + CHECK_ERROR(sock == -1); + int ret; + { + ret = sendbyte(sock, BYTE_DUMPEND); + CHECK_ERROR(ret < 0); + + ret = recvbyte(sock); + CHECK_ERROR(ret < 0); + CHECK_ERROR(ret != BYTE_OK); + result = 1; + } +error: + bss.lock = 0; + return result; +} + +int saviine_readdir(int sock, char * path,char * resultname, int * resulttype, int * filesize){ + while (bss.lock) GX2WaitForVsync(); + bss.lock = 1; + int result = 0; + CHECK_ERROR(sock == -1); int ret; // create and send buffer with : [cmd id][len_path][path][filesize] { @@ -301,13 +408,14 @@ int getFiles(int sock, char * path,char * resultname, int * resulttype, int * fi while (path[size++]); char buffer[1+4+size]; - buffer[0] = BYTE_GET_FILES; + buffer[0] = BYTE_READ_DIR; *(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); + CHECK_ERROR(ret < 0); // wait reply ret = recvbyte(sock); diff --git a/saviine/client/saviine532.ld b/saviine/client/saviine532.ld index 8c39a58..51df7c0 100644 --- a/saviine/client/saviine532.ld +++ b/saviine/client/saviine532.ld @@ -26,6 +26,7 @@ PROVIDE(FSAAddClient = 0x106546c); PROVIDE(FSADelClient = 0x1060aa4); PROVIDE(FSAOpenFile = 0x10621f8); +/*FE3C00*/ /* FS methods */ PROVIDE(FSInit = 0x10683c8); PROVIDE(FSShutdown = 0x1068538); @@ -45,7 +46,7 @@ PROVIDE(FSGetStatFile = 0x106f5a0); PROVIDE(FSIsEof = 0x106f610); PROVIDE(FSWriteFile = 0x106F228); PROVIDE(FSFlushQuota = 0x106FAC8); - +PROVIDE(FSRollbackQuota = 0x106FC48); /* */ PROVIDE(FSGetStat = 0x0106fdc8); diff --git a/saviine/server/src/Program.cs b/saviine/server/src/Program.cs index 06fd765..b8bdbe8 100644 --- a/saviine/server/src/Program.cs +++ b/saviine/server/src/Program.cs @@ -34,9 +34,24 @@ namespace saviine_server 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_READ_DIR = 0xCC; + public const byte BYTE_INJECTSTART = 0x40; + public const byte BYTE_INJECTEND = 0x41; + public const byte BYTE_DUMPSTART = 0x42; + public const byte BYTE_DUMPEND = 0x43; public const byte BYTE_END = 0xfd; + + public const int MASK_NORMAL = 0x8000; + public const int MASK_USER = 0x0100; + public const int MASK_COMMON = 0x0200; + public const int MASK_COMMON_CLEAN = 0x0400; + + + private static long currentPersistentID = 0x0; + private static long COMMON_PERSISTENTID = 0x1; + + [Flags] public enum FSStatFlag : uint { @@ -80,13 +95,16 @@ namespace saviine_server public static string root = "saviine_root"; public static string logs_root = "logs"; + public static string injectfolder = "inject"; + public static string dumpfolder = "dump"; + public static string common = "common"; const uint BUFFER_SIZE = 64 * 1024; static Boolean fastmode = false; static byte op_mode = BYTE_MODE_D; [STAThread] static void Main(string[] args) - { + { if (args.Length > 1) { Console.Error.WriteLine("Usage: saviine_server [fastmode|fast]"); @@ -118,6 +136,7 @@ namespace saviine_server if (op_mode == BYTE_MODE_D) { + currentPersistentID = 0x01; Console.WriteLine("Dump mode"); if(fastmode)Console.WriteLine("Now using fastmode"); } @@ -199,30 +218,7 @@ namespace saviine_server return x; } - - - static string getRealPath(string path,string title_id){ - SaveSelectorDialog ofd = new SaveSelectorDialog(path, title_id); - try - { - DialogResult result = ofd.ShowDialog(); - if (result == System.Windows.Forms.DialogResult.OK) - { - Console.WriteLine("selected: " + ofd.NewPath); - return ofd.NewPath; - } - else - { - Console.WriteLine("nothing selected"); - } - } - catch(Exception e) - { - Console.WriteLine("No saves found to inject"); - } - return ""; - } - + static void Handle(object client_obj) { @@ -295,11 +291,18 @@ namespace saviine_server string mode = reader.ReadString(Encoding.ASCII, len_mode - 1); if (reader.ReadByte() != 0) throw new InvalidDataException(); - path = getRealPathCurrent(path, title_id); + + //Log(log, "old path" + path); + //Log(log, "currentID: " + currentPersistentID); + if (op_mode == BYTE_MODE_I) + path = getRealPathCurrentInject(path, title_id); + + //Log(log, "new path" + path); if (path.Length == 0) failed = true; if (File.Exists(path) && !failed) { + //Log(log, "path exits"); int handle = -1; for (int i = 1; i < files.Length; i++) { @@ -326,6 +329,7 @@ namespace saviine_server writer.Write(handle); break; } + //Log(log, "error fopen"); //else on error: writer.Write(BYTE_NORMAL); @@ -357,18 +361,158 @@ namespace saviine_server } break; } - case BYTE_GET_FILES: + case BYTE_INJECTSTART: { + long wiiUpersistentID = (long)reader.ReadUInt32(); + int dumpCommon = 0; + Boolean injectioncanceled = false; + SaveSelectorDialog ofd = new SaveSelectorDialog(title_id, wiiUpersistentID); + try + { + DialogResult result = ofd.ShowDialog(); + if (result == System.Windows.Forms.DialogResult.OK) + { + currentPersistentID = ofd.NewPersistentID; + dumpCommon = ofd.DumpCommon; + //Console.WriteLine("Injecting " + currentPersistentID.ToString() + " into " + wiiUpersistentID.ToString() + " for title id " + title_id); + if (dumpCommon == 1) Console.WriteLine("clean and inject common folder"); + if (dumpCommon == 2) Console.WriteLine("inject common folder"); + if (dumpCommon > 0 && currentPersistentID == 0) currentPersistentID = COMMON_PERSISTENTID; + } + else + { + Console.WriteLine("Injection canceled"); + injectioncanceled = true; + } + } + catch (Exception e) + { + Console.WriteLine("Injection canceled"); + injectioncanceled = true; + } + if (injectioncanceled) + { + writer.Write(BYTE_NORMAL); + } + else + { + writer.Write(BYTE_SPECIAL); + } + int dumpmask = MASK_NORMAL; + if (currentPersistentID != 0 && currentPersistentID != COMMON_PERSISTENTID) + dumpmask |= MASK_USER; + + if (dumpCommon >= 1) { + dumpmask |= MASK_COMMON; + if(dumpCommon == 2) + dumpmask |= MASK_COMMON_CLEAN; + } + writer.Write(dumpmask); + writer.Write(BYTE_SPECIAL); + + break; + } + case BYTE_INJECTEND: + { + currentPersistentID = 0; + //close all opened files + for (int i = 1; i < files.Length; i++) + { + if (files[i] != null) + { + files[i].Close(); + files[i] = null; + } + } + writer.Write(BYTE_OK); + Console.WriteLine("InjectionEND"); + + break; + } + case BYTE_DUMPSTART: + { + long wiiUpersistentID = (long)reader.ReadUInt32(); + int dumpCommon = 0; + currentPersistentID = wiiUpersistentID; + dumpCommon = 1; + /* + Boolean injectioncanceled = false; + SaveSelectorDialog ofd = new SaveSelectorDialog(title_id, wiiUpersistentID); + try + { + DialogResult result = ofd.ShowDialog(); + if (result == System.Windows.Forms.DialogResult.OK) + { + currentPersistentID = ofd.NewPersistentID; + dumpCommon = ofd.DumpCommon; + //Console.WriteLine("Injecting " + currentPersistentID.ToString() + " into " + wiiUpersistentID.ToString() + " for title id " + title_id); + if (dumpCommon == 1) Console.WriteLine("clean and inject common folder"); + if (dumpCommon == 2) Console.WriteLine("inject common folder"); + if (dumpCommon > 0 && currentPersistentID == 0) currentPersistentID = COMMON_PERSISTENTID; + } + else + { + Console.WriteLine("dump canceled"); + injectioncanceled = true; + } + } + catch (Exception e) + { + Console.WriteLine("dump canceled"); + injectioncanceled = true; + } + if (injectioncanceled) + { + writer.Write(BYTE_NORMAL); + } + else + { + writer.Write(BYTE_SPECIAL); + }*/ + writer.Write(BYTE_SPECIAL); + int dumpmask = MASK_NORMAL; + if (currentPersistentID != 0 && currentPersistentID != COMMON_PERSISTENTID) + dumpmask |= MASK_USER; + + if (dumpCommon == 1) + { + dumpmask |= MASK_COMMON; + } + writer.Write(dumpmask); + writer.Write(BYTE_SPECIAL); + + break; + } + case BYTE_DUMPEND: + { + currentPersistentID = 0; + //close all opened files + for (int i = 1; i < files.Length; i++) + { + if (files[i] != null) + { + files[i].Close(); + files[i] = null; + } + } + writer.Write(BYTE_OK); + Console.WriteLine("dumpEND"); + + break; + } + case BYTE_READ_DIR: + { Boolean failed = false; int len_path = reader.ReadInt32(); string path = reader.ReadString(Encoding.ASCII, len_path-1); if (reader.ReadByte() != 0) throw new InvalidDataException(); int x = 0; - - currentPersistentID = getPersistentIDFromPath(path); - path = getRealPath(path, title_id); + //Console.WriteLine("old" + path); + if(op_mode == BYTE_MODE_I) + path = getRealPathCurrentInject(path, title_id); + //Console.WriteLine("new" + path); if(path.Length == 0)failed = true; - + if (Directory.Exists(path) && !failed) { x = countDirectory(path); @@ -433,7 +577,7 @@ namespace saviine_server } writer.Write(BYTE_END); // //Console.Write("list was empty return BYTE_END \n"); - + //Console.Write("in break \n"); break; } @@ -464,9 +608,13 @@ namespace saviine_server 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"); + if (offset == sz) + { + Console.Write("\n"); + log.Write("\r\t--> {0}% ({1} kB / {2} kB)\n", strProgress, strCurrent, strSize); + } int ret = -5; if ((ret =reader.ReadByte()) != BYTE_OK) { @@ -486,13 +634,24 @@ namespace saviine_server int len_path = reader.ReadInt32(); string path = reader.ReadString(Encoding.ASCII, len_path - 1); if (reader.ReadByte() != 0) throw new InvalidDataException(); - if (!Directory.Exists(LocalRootDump + path)) + //Console.WriteLine("old " + path); + if (op_mode == BYTE_MODE_D) + path = getRealPathCurrentDump(path, title_id); + //Console.WriteLine("new " + path); + + if (path.Length == 0) { - Directory.CreateDirectory(Path.GetDirectoryName(LocalRootDump + path)); + writer.Write(BYTE_SPECIAL); + break; + } + + if (!Directory.Exists(path)) + { + Directory.CreateDirectory(Path.GetDirectoryName(path)); } // Add new file for incoming data - files_request.Add(fd, new FileStream(LocalRootDump + path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write)); + files_request.Add(fd, new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write)); // Send response if (fastmode) { writer.Write(BYTE_REQUEST); @@ -652,40 +811,43 @@ namespace saviine_server Console.WriteLine(name + " Exit"); } - private static string getPersistentIDFromPath(string path) + private static string getRealPathCurrentInject(string path, string title_id) { + return getRealPathCurrent(injectfolder, path, title_id); + } + private static string getRealPathCurrentDump(string path, string title_id) + { + return getRealPathCurrent(dumpfolder, path, title_id); + } + + private static string getRealPathCurrent(string prefix, string path, string title_id) + { + string savePath = Program.root + "/" + prefix + "/" + title_id; + if (currentPersistentID == 0) return ""; string[] stringSeparators = new string[] { "vol/save/", "vol\\save\\" }; string[] result; - string resultstr = ""; - + string resultstr = ""; result = path.Split(stringSeparators, StringSplitOptions.None); - if (result.Length < 2) return ""; - resultstr = result[result.Length-1]; + if (result.Length < 2) return ""; + resultstr = result[result.Length-1]; stringSeparators = new string[] { "/", "\\" }; result = resultstr.Split(stringSeparators, StringSplitOptions.None); - if (result.Length < 1) return ""; - return result[0]; - } - private static string currentPersistentID = "80000009"; - private static string getRealPathCurrent(string path, string title_id) - { - if (currentPersistentID.Length == 0) return ""; - string[] stringSeparators = new string[] { "vol/save/", "vol\\save\\" }; - string[] result; - string resultstr = ""; - - result = path.Split(stringSeparators, StringSplitOptions.None); - if (result.Length < 2) return ""; - resultstr = result[result.Length-1]; - stringSeparators = new string[] { "/", "\\" }; - result = resultstr.Split(stringSeparators, StringSplitOptions.None); - if (result.Length < 2) return ""; + if (result.Length < 2) + { + if (result[0] != "common") return savePath + "/" + String.Format("{0:X}", currentPersistentID); + return savePath + "/" + "common"; + } resultstr = ""; + if (result[0] != "common") + savePath += "/" + String.Format("{0:X}", currentPersistentID); + else + savePath += "/" + "common"; for (int i = 1; i < result.Length; i++) { resultstr += "/" + result[i]; } - string savePath = Program.root + "/" + "inject" + "/" + title_id + "/" + currentPersistentID + resultstr; + + savePath += resultstr; return savePath; } diff --git a/saviine/server/src/SaveSelectorDialog.Designer.cs b/saviine/server/src/SaveSelectorDialog.Designer.cs index f69b463..3c9a64a 100644 --- a/saviine/server/src/SaveSelectorDialog.Designer.cs +++ b/saviine/server/src/SaveSelectorDialog.Designer.cs @@ -30,15 +30,19 @@ { this.btn_ok = new System.Windows.Forms.Button(); this.btn_cancel = new System.Windows.Forms.Button(); - this.listBox_saves = new System.Windows.Forms.ListBox(); + this.lbl_message = new System.Windows.Forms.Label(); + this.comBoxIDList = new System.Windows.Forms.ComboBox(); + this.label1 = new System.Windows.Forms.Label(); + this.Inj = new System.Windows.Forms.Label(); + this.comBoxCommon = new System.Windows.Forms.ComboBox(); this.SuspendLayout(); // // btn_ok // this.btn_ok.DialogResult = System.Windows.Forms.DialogResult.OK; - this.btn_ok.Location = new System.Drawing.Point(167, 266); + this.btn_ok.Location = new System.Drawing.Point(62, 133); this.btn_ok.Name = "btn_ok"; - this.btn_ok.Size = new System.Drawing.Size(105, 33); + this.btn_ok.Size = new System.Drawing.Size(81, 21); this.btn_ok.TabIndex = 0; this.btn_ok.Text = "OK"; this.btn_ok.UseVisualStyleBackColor = true; @@ -47,33 +51,80 @@ // btn_cancel // this.btn_cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.btn_cancel.Location = new System.Drawing.Point(332, 269); + this.btn_cancel.Location = new System.Drawing.Point(198, 133); this.btn_cancel.Name = "btn_cancel"; - this.btn_cancel.Size = new System.Drawing.Size(130, 29); + this.btn_cancel.Size = new System.Drawing.Size(81, 21); this.btn_cancel.TabIndex = 1; this.btn_cancel.Text = "Cancel"; this.btn_cancel.UseVisualStyleBackColor = true; // - // listBox_saves + // lbl_message // - this.listBox_saves.FormattingEnabled = true; - this.listBox_saves.Location = new System.Drawing.Point(54, 48); - this.listBox_saves.Name = "listBox_saves"; - this.listBox_saves.Size = new System.Drawing.Size(408, 160); - this.listBox_saves.TabIndex = 2; + this.lbl_message.AutoSize = true; + this.lbl_message.Location = new System.Drawing.Point(12, 10); + this.lbl_message.Name = "lbl_message"; + this.lbl_message.Size = new System.Drawing.Size(236, 13); + this.lbl_message.TabIndex = 3; + this.lbl_message.Text = "Got an injection request for 00050000-10157F00"; // - // Form1 + // comBoxIDList + // + this.comBoxIDList.FormattingEnabled = true; + this.comBoxIDList.Location = new System.Drawing.Point(186, 48); + this.comBoxIDList.Name = "comBoxIDList"; + this.comBoxIDList.Size = new System.Drawing.Size(93, 21); + this.comBoxIDList.TabIndex = 4; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(12, 51); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(81, 13); + this.label1.TabIndex = 5; + this.label1.Text = "Select userdata"; + this.label1.Click += new System.EventHandler(this.label1_Click); + // + // Inj + // + this.Inj.AutoSize = true; + this.Inj.Location = new System.Drawing.Point(12, 86); + this.Inj.Name = "Inj"; + this.Inj.Size = new System.Drawing.Size(108, 13); + this.Inj.TabIndex = 7; + this.Inj.Text = "Inject common save?"; + this.Inj.Click += new System.EventHandler(this.Inj_Click); + // + // comBoxCommon + // + this.comBoxCommon.FormattingEnabled = true; + this.comBoxCommon.Items.AddRange(new object[] { + "no", + "inject", + "clean and inject (deleting existing common)"}); + this.comBoxCommon.Location = new System.Drawing.Point(126, 83); + this.comBoxCommon.Name = "comBoxCommon"; + this.comBoxCommon.Size = new System.Drawing.Size(153, 21); + this.comBoxCommon.TabIndex = 8; + // + // SaveSelectorDialog // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(499, 314); - this.Controls.Add(this.listBox_saves); + this.ClientSize = new System.Drawing.Size(310, 166); + this.Controls.Add(this.comBoxCommon); + this.Controls.Add(this.Inj); + this.Controls.Add(this.label1); + this.Controls.Add(this.comBoxIDList); + this.Controls.Add(this.lbl_message); this.Controls.Add(this.btn_cancel); this.Controls.Add(this.btn_ok); - this.Name = "Form1"; - this.Text = "Form1"; + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.Name = "SaveSelectorDialog"; + this.Text = "Injection request"; this.Load += new System.EventHandler(this.Form1_Load); this.ResumeLayout(false); + this.PerformLayout(); } @@ -81,6 +132,10 @@ private System.Windows.Forms.Button btn_ok; private System.Windows.Forms.Button btn_cancel; - private System.Windows.Forms.ListBox listBox_saves; + private System.Windows.Forms.Label lbl_message; + private System.Windows.Forms.ComboBox comBoxIDList; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label Inj; + private System.Windows.Forms.ComboBox comBoxCommon; } } \ No newline at end of file diff --git a/saviine/server/src/SaveSelectorDialog.cs b/saviine/server/src/SaveSelectorDialog.cs index be599b5..6159cf0 100644 --- a/saviine/server/src/SaveSelectorDialog.cs +++ b/saviine/server/src/SaveSelectorDialog.cs @@ -12,40 +12,61 @@ namespace saviine_server { public partial class SaveSelectorDialog : Form { - private string newPath = ""; + private long newPersistentID = 0; + private int dumpCommon = 0; - public string NewPath + public long NewPersistentID { - get { return newPath; } + get { return newPersistentID; } } - private static string savePath = Program.root + "/" + "inject"; - public SaveSelectorDialog(string path,string title_id) + public int DumpCommon + { + get { return dumpCommon; } + } + private static string savePath; + public SaveSelectorDialog(string title_id,long persistentID) { InitializeComponent(); - string[] stringSeparators = new string[] { "vol/save/", "vol\\save\\" }; - string[] result; - - result = path.Split(stringSeparators, StringSplitOptions.None); - if (result.Length < 2) this.Close(); - string resultPath = result[result.Length-2]; - - Console.WriteLine(title_id); + comBoxCommon.SelectedIndex = 0; + savePath = Program.root + "/" + Program.injectfolder;; + this.lbl_message.Text = "Got an injection request for " + title_id; savePath += "/" + title_id; + string[] subdirectoryEntries; if (Directory.Exists(savePath)) { // Recurse into subdirectories of this directory. - string[] subdirectoryEntries = Directory.GetDirectories(savePath); + subdirectoryEntries = Directory.GetDirectories(savePath); + this.comBoxIDList.Items.Add("---none---"); + comBoxIDList.SelectedIndex = 0; foreach (string subdirectory in subdirectoryEntries) { - this.listBox_saves.Items.Add(Path.GetFileName(subdirectory)); + string filename = Path.GetFileName(subdirectory); + long id; + try{ + id = Convert.ToUInt32(filename, 16); + }catch (Exception){ + id = 0; + } + + + if (id >= 0x80000000 && id <= 0x81000000) + { + + this.comBoxIDList.Items.Add(filename); + } + } + if (comBoxIDList.Items.Count == 1) + { + this.comBoxIDList.Enabled = false; + + } + if (!Directory.Exists(savePath + "/" + Program.common)) + { + comBoxCommon.Enabled = false; } } - else - { - Console.WriteLine("dir not found! " + savePath); - this.Close(); - } - + + } private void Form1_Load(object sender, EventArgs e) @@ -55,12 +76,34 @@ namespace saviine_server private void btn_ok_Click(object sender, EventArgs e) { - newPath = savePath + "/" + this.listBox_saves.SelectedItem.ToString(); + long id; + try + { + id = Convert.ToUInt32(this.comBoxIDList.SelectedItem.ToString(), 16); + } + catch (Exception) + { + id = 0; + } + newPersistentID = id; + dumpCommon = comBoxCommon.SelectedIndex; + Console.WriteLine(dumpCommon); + } private void btn_cancel_Click(object sender, EventArgs e) { } + + private void Inj_Click(object sender, EventArgs e) + { + + } + + private void label1_Click(object sender, EventArgs e) + { + + } } diff --git a/saviine/server/src/bin/saviine_server.exe b/saviine/server/src/bin/saviine_server.exe index 6ea09a5..9aea226 100644 Binary files a/saviine/server/src/bin/saviine_server.exe and b/saviine/server/src/bin/saviine_server.exe differ diff --git a/saviine/server/src/obj/x86/Debug/saviine_server.SaveSelectorDialog.resources b/saviine/server/src/obj/x86/Debug/saviine_server.SaveSelectorDialog.resources new file mode 100644 index 0000000..6c05a97 Binary files /dev/null and b/saviine/server/src/obj/x86/Debug/saviine_server.SaveSelectorDialog.resources differ diff --git a/saviine/server/src/obj/x86/Debug/saviine_server.csproj.FileListAbsolute.txt b/saviine/server/src/obj/x86/Debug/saviine_server.csproj.FileListAbsolute.txt index ef3b3e3..4e3310e 100644 --- a/saviine/server/src/obj/x86/Debug/saviine_server.csproj.FileListAbsolute.txt +++ b/saviine/server/src/obj/x86/Debug/saviine_server.csproj.FileListAbsolute.txt @@ -1,8 +1,8 @@ G:\Programmieren\libwiiu-master\saviinet\saviine\saviine\server\src\bin\saviine_server.exe.config G:\Programmieren\libwiiu-master\saviinet\saviine\saviine\server\src\bin\saviine_server.exe G:\Programmieren\libwiiu-master\saviinet\saviine\saviine\server\src\bin\saviine_server.pdb -G:\Programmieren\libwiiu-master\saviinet\saviine\saviine\server\src\obj\x86\Debug\saviine_server.csprojResolveAssemblyReference.cache G:\Programmieren\libwiiu-master\saviinet\saviine\saviine\server\src\obj\x86\Debug\saviine_server.exe G:\Programmieren\libwiiu-master\saviinet\saviine\saviine\server\src\obj\x86\Debug\saviine_server.pdb -G:\Programmieren\libwiiu-master\saviinet\saviine\saviine\server\src\obj\x86\Debug\saviine_server.Form1.resources G:\Programmieren\libwiiu-master\saviinet\saviine\saviine\server\src\obj\x86\Debug\saviine_server.csproj.GenerateResource.Cache +G:\Programmieren\libwiiu-master\saviinet\saviine\saviine\server\src\obj\x86\Debug\saviine_server.SaveSelectorDialog.resources +G:\Programmieren\libwiiu-master\saviinet\saviine\saviine\server\src\obj\x86\Debug\saviine_server.csprojResolveAssemblyReference.cache diff --git a/saviine/server/src/obj/x86/Debug/saviine_server.csprojResolveAssemblyReference.cache b/saviine/server/src/obj/x86/Debug/saviine_server.csprojResolveAssemblyReference.cache index 7b16748..5f8b667 100644 Binary files a/saviine/server/src/obj/x86/Debug/saviine_server.csprojResolveAssemblyReference.cache and b/saviine/server/src/obj/x86/Debug/saviine_server.csprojResolveAssemblyReference.cache differ diff --git a/saviine/server/src/saviine_server.v12.suo b/saviine/server/src/saviine_server.v12.suo index 5bd20b5..4ceec0a 100644 Binary files a/saviine/server/src/saviine_server.v12.suo and b/saviine/server/src/saviine_server.v12.suo differ