Fix crashes on "Refresh Liveara" w PSM (#560)

* Fix Crashing when installing PSM

* removed redundant variable from refresh.c

* Change { location

* Change location of "{

* Change location of "{"

* move int ret;

* fix mixed tabs/spaces

* fix return indentation
This commit is contained in:
Bluzume 2020-04-21 18:09:55 +12:00 committed by GitHub
parent f8201252bd
commit 42fcc22517
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 186 additions and 61 deletions

2
main.h
View File

@ -54,7 +54,7 @@
// VitaShell version major.minor // VitaShell version major.minor
#define VITASHELL_VERSION_MAJOR 0x02 #define VITASHELL_VERSION_MAJOR 0x02
#define VITASHELL_VERSION_MINOR 0x02 #define VITASHELL_VERSION_MINOR 0x00
#define VITASHELL_VERSION ((VITASHELL_VERSION_MAJOR << 0x18) | (VITASHELL_VERSION_MINOR << 0x10)) #define VITASHELL_VERSION ((VITASHELL_VERSION_MAJOR << 0x18) | (VITASHELL_VERSION_MINOR << 0x10))

View File

@ -48,6 +48,47 @@ static int unloadScePaf() {
return sceSysmoduleUnloadModuleInternalWithArg(SCE_SYSMODULE_INTERNAL_PAF, 0, NULL, &buf); return sceSysmoduleUnloadModuleInternalWithArg(SCE_SYSMODULE_INTERNAL_PAF, 0, NULL, &buf);
} }
int promotePsm(const char *path, const char *titleid) {
int res;
ScePromoterUtilityImportParams promoteArgs;
memset(&promoteArgs,0x00,sizeof(ScePromoterUtilityImportParams));
strncpy(promoteArgs.path,path,0x7F);
strncpy(promoteArgs.titleid,titleid,0xB);
promoteArgs.type = SCE_PKG_TYPE_PSM;
promoteArgs.attribute = 0x1;
res = loadScePaf();
if (res < 0)
return res;
res = sceSysmoduleLoadModuleInternal(SCE_SYSMODULE_INTERNAL_PROMOTER_UTIL);
if (res < 0)
return res;
res = scePromoterUtilityInit();
if (res < 0)
return res;
res = scePromoterUtilityPromoteImport(&promoteArgs);
if (res < 0)
return res;
res = scePromoterUtilityExit();
if (res < 0)
return res;
res = sceSysmoduleUnloadModuleInternal(SCE_SYSMODULE_INTERNAL_PROMOTER_UTIL);
if (res < 0)
return res;
res = unloadScePaf();
if (res < 0)
return res;
return res;
}
int promoteApp(const char *path) { int promoteApp(const char *path) {
int res; int res;

View File

@ -29,6 +29,7 @@ typedef struct {
} InstallArguments; } InstallArguments;
int promoteApp(const char *path); int promoteApp(const char *path);
int promotePsm(const char *path, const char *titleid);
int deleteApp(const char *titleid); int deleteApp(const char *titleid);
int checkAppExist(const char *titleid); int checkAppExist(const char *titleid);

203
refresh.c
View File

@ -3,6 +3,7 @@
Copyright (C) 2015-2018, TheFloW Copyright (C) 2015-2018, TheFloW
Copyright (C) 2017, VitaSmith Copyright (C) 2017, VitaSmith
Copyright (C) 2018, TheRadziu Copyright (C) 2018, TheRadziu
Copyright (C) 2020, SilicaAndPina
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -36,13 +37,12 @@
#define APP_TEMP "ux0:temp/app" #define APP_TEMP "ux0:temp/app"
#define DLC_TEMP "ux0:temp/addcont" #define DLC_TEMP "ux0:temp/addcont"
#define PATCH_TEMP "ux0:temp/patch" #define PATCH_TEMP "ux0:temp/patch"
#define PSM_TEMP "ux0:temp/psm" #define PSM_TEMP "ux0:temp/game"
#define THEME_TEMP "ux0:temp/theme" #define THEME_TEMP "ux0:temp/theme"
#define MAX_DLC_PER_TITLE 1024 #define MAX_DLC_PER_TITLE 1024
int isCustomHomebrew(const char* path) int isCustomHomebrew(const char* path) {
{
uint32_t work[RIF_SIZE/4]; uint32_t work[RIF_SIZE/4];
if (ReadFile(path, work, sizeof(work)) != sizeof(work)) if (ReadFile(path, work, sizeof(work)) != sizeof(work))
@ -55,82 +55,115 @@ int isCustomHomebrew(const char* path)
return 1; return 1;
} }
int refreshNeeded(const char *app_path, const char* content_type)
{
char sfo_path[MAX_PATH_LENGTH]; int refreshNeeded(const char *app_path, const char* content_type) {
char appmeta_path[MAX_PATH_LENGTH]; char appmeta_path[MAX_PATH_LENGTH];
char appmeta_param[MAX_PATH_LENGTH]; char appmeta_param[MAX_PATH_LENGTH];
char sfo_path[MAX_PATH_LENGTH];
int mounted_appmeta; int mounted_appmeta;
// Read param.sfo
snprintf(sfo_path, MAX_PATH_LENGTH, "%s/sce_sys/param.sfo", app_path);
void *sfo_buffer = NULL;
int sfo_size = allocateReadFile(sfo_path, &sfo_buffer);
if (sfo_size < 0)
return sfo_size;
// Get title and content ids
char titleid[12], contentid[50], appver[8]; char titleid[12], contentid[50], appver[8];
getSfoString(sfo_buffer, "TITLE_ID", titleid, sizeof(titleid)); if(strcmp(content_type,"psm") == 0)
getSfoString(sfo_buffer, "CONTENT_ID", contentid, sizeof(contentid)); {
getSfoString(sfo_buffer, "APP_VER", appver, sizeof(appver)); char contentid_path[MAX_PATH_LENGTH];
void *cidFile = NULL;
//Initalize buffers
memset(titleid,0,12);
memset(contentid,0,50);
memset(appver,0,8);
snprintf(contentid_path, MAX_PATH_LENGTH, "%s/RW/System/content_id", app_path);
// Get content id
int contentid_size = allocateReadFile(contentid_path, &cidFile);
if(contentid_size != 48) //Check if valid contentid file
return 0;
// Get title id from content id
strncpy(titleid,cidFile+7,9);
strncpy(contentid,cidFile,49);
free(cidFile);
}
else {
// Read param.sfo
snprintf(sfo_path, MAX_PATH_LENGTH, "%s/sce_sys/param.sfo", app_path);
void *sfo_buffer = NULL;
int sfo_size = allocateReadFile(sfo_path, &sfo_buffer);
if (sfo_size < 0)
return 0;
// Free sfo buffer // Get title and content ids
free(sfo_buffer);
getSfoString(sfo_buffer, "TITLE_ID", titleid, sizeof(titleid));
getSfoString(sfo_buffer, "CONTENT_ID", contentid, sizeof(contentid));
getSfoString(sfo_buffer, "APP_VER", appver, sizeof(appver));
// Free sfo buffer
free(sfo_buffer);
}
// Check if app or dlc exists // Check if app or dlc exists
if (((strcmp(content_type, "app") == 0)||(strcmp(content_type, "dlc") == 0))&&(checkAppExist(titleid))) { if (((strcmp(content_type, "app") == 0)||(strcmp(content_type, "dlc") == 0)||(strcmp(content_type,"psm") == 0))&&(checkAppExist(titleid))) {
char rif_name[48]; char rif_name[48];
char rif_path[MAX_PATH_LENGTH];
uint64_t aid; uint64_t aid;
sceRegMgrGetKeyBin("/CONFIG/NP", "account_id", &aid, sizeof(uint64_t)); sceRegMgrGetKeyBin("/CONFIG/NP", "account_id", &aid, sizeof(uint64_t));
// Check if bounded rif file exits // Check if bounded rif file exits
_sceNpDrmGetRifName(rif_name, 0, aid); _sceNpDrmGetRifName(rif_name, 0, aid);
if (strcmp(content_type, "app") == 0) if (strcmp(content_type, "app") == 0)
snprintf(sfo_path, MAX_PATH_LENGTH, "ux0:license/app/%s/%s", titleid, rif_name); snprintf(rif_path, MAX_PATH_LENGTH, "ux0:license/app/%s/%s", titleid, rif_name);
else if (strcmp(content_type, "dlc") == 0) else if (strcmp(content_type, "dlc") == 0)
snprintf(sfo_path, MAX_PATH_LENGTH, "ux0:license/addcont/%s/%s/%s", titleid, &contentid[20], rif_name); snprintf(rif_path, MAX_PATH_LENGTH, "ux0:license/addcont/%s/%s/%s", titleid, &contentid[20], rif_name);
if (checkFileExist(sfo_path)) if (checkFileExist(rif_path))
return 0; return 0;
// Check if fixed rif file exits // Check if fixed rif file exits
_sceNpDrmGetFixedRifName(rif_name, 0, 0); _sceNpDrmGetFixedRifName(rif_name, 0, 0);
if (strcmp(content_type, "app") == 0) if (strcmp(content_type, "app") == 0)
snprintf(sfo_path, MAX_PATH_LENGTH, "ux0:license/app/%s/%s", titleid, rif_name); snprintf(rif_path, MAX_PATH_LENGTH, "ux0:license/app/%s/%s", titleid, rif_name);
else if (strcmp(content_type, "dlc") == 0) else if (strcmp(content_type, "dlc") == 0)
snprintf(sfo_path, MAX_PATH_LENGTH, "ux0:license/addcont/%s/%s/%s", titleid, &contentid[20], rif_name); snprintf(rif_path, MAX_PATH_LENGTH, "ux0:license/addcont/%s/%s/%s", titleid, &contentid[20], rif_name);
if (checkFileExist(sfo_path)) if (checkFileExist(rif_path))
return 0; return 0;
}
if(strcmp(content_type,"psm") == 0)
return 0;
}
// Check if patch for installed app exists // Check if patch for installed app exists
else if (strcmp(content_type, "patch") == 0) { else if (strcmp(content_type, "patch") == 0) {
if (!checkAppExist(titleid)) if (!checkAppExist(titleid))
return 0; return 0;
if (checkFileExist(sfo_path)) { if (checkFileExist(sfo_path)) {
void *sfo_buffer = NULL;
snprintf(appmeta_path, MAX_PATH_LENGTH, "ux0:appmeta/%s", titleid); snprintf(appmeta_path, MAX_PATH_LENGTH, "ux0:appmeta/%s", titleid);
pfsUmount(); pfsUmount();
if(pfsMount(appmeta_path)<0) if(pfsMount(appmeta_path)<0)
return 0; return 0;
//Now read it //Now read it
snprintf(appmeta_param, MAX_PATH_LENGTH, "ux0:appmeta/%s/param.sfo", titleid); snprintf(appmeta_param, MAX_PATH_LENGTH, "ux0:appmeta/%s/param.sfo", titleid);
int sfo_size = allocateReadFile(appmeta_param, &sfo_buffer); int sfo_size = allocateReadFile(appmeta_param, &sfo_buffer);
if (sfo_size < 0) if (sfo_size < 0)
return sfo_size; return sfo_size;
char promoted_appver[8]; char promoted_appver[8];
getSfoString(sfo_buffer, "APP_VER", promoted_appver, sizeof(promoted_appver)); getSfoString(sfo_buffer, "APP_VER", promoted_appver, sizeof(promoted_appver));
pfsUmount(); pfsUmount();
//Finally compare it //Finally compare it
if (strcmp(appver, promoted_appver) == 0) if (strcmp(appver, promoted_appver) == 0)
return 0; return 0;
} }
} }
return 1; return 1;
} }
int refreshApp(const char *app_path) int refreshApp(const char *app_path) {
{
char work_bin_path[MAX_PATH_LENGTH]; char work_bin_path[MAX_PATH_LENGTH];
int res; int res;
@ -166,8 +199,7 @@ int refreshApp(const char *app_path)
} }
// target_type should be either SCE_S_IFREG for files or SCE_S_IFDIR for directories // target_type should be either SCE_S_IFREG for files or SCE_S_IFDIR for directories
int parse_dir_with_callback(int target_type, const char* path, void(*callback)(void*, const char*, const char*), void* data) int parse_dir_with_callback(int target_type, const char* path, void(*callback)(void*, const char*, const char*), void* data) {
{
SceUID dfd = sceIoDopen(path); SceUID dfd = sceIoDopen(path);
if (dfd >= 0) { if (dfd >= 0) {
int res = 0; int res = 0;
@ -216,8 +248,7 @@ typedef struct {
uint8_t* rif; uint8_t* rif;
} license_data_t; } license_data_t;
void app_callback(void* data, const char* dir, const char* subdir) void app_callback(void* data, const char* dir, const char* subdir) {
{
refresh_data_t *refresh_data = (refresh_data_t*)data; refresh_data_t *refresh_data = (refresh_data_t*)data;
char path[MAX_PATH_LENGTH]; char path[MAX_PATH_LENGTH];
@ -242,8 +273,7 @@ void app_callback(void* data, const char* dir, const char* subdir)
} }
} }
void dlc_callback_inner(void* data, const char* dir, const char* subdir) void dlc_callback_inner(void* data, const char* dir, const char* subdir) {
{
dlc_data_t *dlc_data = (dlc_data_t*)data; dlc_data_t *dlc_data = (dlc_data_t*)data;
char path[MAX_PATH_LENGTH]; char path[MAX_PATH_LENGTH];
@ -260,8 +290,7 @@ void dlc_callback_inner(void* data, const char* dir, const char* subdir)
} }
} }
void dlc_callback_outer(void* data, const char* dir, const char* subdir) void dlc_callback_outer(void* data, const char* dir, const char* subdir) {
{
refresh_data_t *refresh_data = (refresh_data_t*)data; refresh_data_t *refresh_data = (refresh_data_t*)data;
dlc_data_t dlc_data; dlc_data_t dlc_data;
dlc_data.refresh_data = refresh_data; dlc_data.refresh_data = refresh_data;
@ -303,8 +332,7 @@ void dlc_callback_outer(void* data, const char* dir, const char* subdir)
} }
} }
void patch_callback(void* data, const char* dir, const char* subdir) void patch_callback(void* data, const char* dir, const char* subdir) {
{
refresh_data_t *refresh_data = (refresh_data_t*)data; refresh_data_t *refresh_data = (refresh_data_t*)data;
char path[MAX_PATH_LENGTH]; char path[MAX_PATH_LENGTH];
@ -326,8 +354,56 @@ void patch_callback(void* data, const char* dir, const char* subdir)
} }
} }
int refresh_thread(SceSize args, void *argp) void psm_callback(void* data, const char* dir, const char* subdir) {
{ refresh_data_t *refresh_data = (refresh_data_t*)data;
char path[MAX_PATH_LENGTH];
if (strcasecmp(subdir, vitashell_titleid) == 0)
return;
if (refresh_data->refresh_pass) {
snprintf(path, MAX_PATH_LENGTH, "%s/%s", dir, subdir);
if (refreshNeeded(path, "psm")) {
char contentid_path[MAX_PATH_LENGTH];
snprintf(contentid_path, MAX_PATH_LENGTH, "%s/RW/System/content_id", path);
char titleid[12];
void *cidFile = NULL;
// Initalize Bufer
memset(titleid,0,12);
// Get content id
allocateReadFile(contentid_path, &cidFile);
// Get title id from content id
strncpy(titleid,cidFile+7,9);
//free buffers
free(cidFile);
// Get promote path
char promote_path[MAX_PATH_LENGTH];
snprintf(promote_path,MAX_PATH_LENGTH,"%s/%s",PSM_TEMP,titleid);
// Move the directory to temp for installation
removePath(promote_path, NULL);
sceIoRename(path, promote_path);
// Finally call promote
if (promotePsm(PSM_TEMP,titleid) == 0)
refresh_data->refreshed++;
else
sceIoRename(promote_path, path); // Restore folder on error
}
SetProgress(++refresh_data->processed, refresh_data->count);
} else {
refresh_data->count++;
}
}
int refresh_thread(SceSize args, void *argp) {
SceUID thid = -1; SceUID thid = -1;
refresh_data_t refresh_data = { 0, 0, 0, 0 }; refresh_data_t refresh_data = { 0, 0, 0, 0 };
@ -350,13 +426,18 @@ int refresh_thread(SceSize args, void *argp)
if (parse_dir_with_callback(SCE_S_IFDIR, "ux0:patch", patch_callback, &refresh_data) < 0) if (parse_dir_with_callback(SCE_S_IFDIR, "ux0:patch", patch_callback, &refresh_data) < 0)
goto EXIT; goto EXIT;
// Get the psm count
if (parse_dir_with_callback(SCE_S_IFDIR, "ux0:psm", psm_callback, &refresh_data) < 0)
goto EXIT;
// Update thread // Update thread
thid = createStartUpdateThread(refresh_data.count, 0); thid = createStartUpdateThread(refresh_data.count, 0);
// Make sure we have the temp directories we need // Make sure we have the temp directories we need
sceIoMkdir("ux0:temp", 0006); sceIoMkdir("ux0:temp", 0006);
sceIoMkdir("ux0:temp/addcont", 0006); sceIoMkdir(DLC_TEMP, 0006);
sceIoMkdir("ux0:temp/patch", 0006); sceIoMkdir(PATCH_TEMP, 0006);
sceIoMkdir(PSM_TEMP, 0006);
refresh_data.refresh_pass = 1; refresh_data.refresh_pass = 1;
// Refresh apps // Refresh apps
@ -366,13 +447,18 @@ int refresh_thread(SceSize args, void *argp)
// Refresh dlc // Refresh dlc
if (parse_dir_with_callback(SCE_S_IFDIR, "ux0:addcont", dlc_callback_outer, &refresh_data) < 0) if (parse_dir_with_callback(SCE_S_IFDIR, "ux0:addcont", dlc_callback_outer, &refresh_data) < 0)
goto EXIT; goto EXIT;
// Refresh patch // Refresh patch
if (parse_dir_with_callback(SCE_S_IFDIR, "ux0:patch", patch_callback, &refresh_data) < 0) if (parse_dir_with_callback(SCE_S_IFDIR, "ux0:patch", patch_callback, &refresh_data) < 0)
goto EXIT; goto EXIT;
sceIoRmdir("ux0:temp/addcont"); // Refresh psm
sceIoRmdir("ux0:temp/patch"); if (parse_dir_with_callback(SCE_S_IFDIR, "ux0:psm", psm_callback, &refresh_data) < 0)
goto EXIT;
sceIoRmdir(DLC_TEMP);
sceIoRmdir(PATCH_TEMP);
sceIoRmdir(PSM_TEMP);
// Set progress to 100% // Set progress to 100%
sceMsgDialogProgressBarSetValue(SCE_MSG_DIALOG_PROGRESSBAR_TARGET_BAR_DEFAULT, 100); sceMsgDialogProgressBarSetValue(SCE_MSG_DIALOG_PROGRESSBAR_TARGET_BAR_DEFAULT, 100);
@ -396,8 +482,7 @@ EXIT:
// Note: This is currently not optimized AT ALL. // Note: This is currently not optimized AT ALL.
// Ultimately, we want to use a single transaction and avoid trying to // Ultimately, we want to use a single transaction and avoid trying to
// re-insert rifs that are already present. // re-insert rifs that are already present.
void license_file_callback(void* data, const char* dir, const char* file) void license_file_callback(void* data, const char* dir, const char* file) {
{
license_data_t *license_data = (license_data_t*)data; license_data_t *license_data = (license_data_t*)data;
char path[MAX_PATH_LENGTH]; char path[MAX_PATH_LENGTH];
@ -421,8 +506,7 @@ void license_file_callback(void* data, const char* dir, const char* file)
} }
} }
void license_dir_callback(void* data, const char* dir, const char* subdir) void license_dir_callback(void* data, const char* dir, const char* subdir) {
{
license_data_t *license_data = (license_data_t*)data; license_data_t *license_data = (license_data_t*)data;
char path[MAX_PATH_LENGTH]; char path[MAX_PATH_LENGTH];
@ -434,8 +518,7 @@ void license_dir_callback(void* data, const char* dir, const char* subdir)
license_data->cur_depth--; license_data->cur_depth--;
} }
int license_thread(SceSize args, void *argp) int license_thread(SceSize args, void *argp) {
{
SceUID thid = -1; SceUID thid = -1;
license_data_t license_data = { 0, 0, 0, 0, 0, 1, malloc(RIF_SIZE) }; license_data_t license_data = { 0, 0, 0, 0, 0, 1, malloc(RIF_SIZE) };