diff --git a/main.c b/main.c index ca216f7..af1efd0 100644 --- a/main.c +++ b/main.c @@ -20,6 +20,68 @@ int sceAppInstUtilInitialize(void); int sceAppInstUtilAppInstallTitleDir(const char* title_id, const char* install_path, void* reserved); int sceAppInstUtilAppInstallAll(void* reserved); +#define SHADOWMOUNTPLUS_NOAUTOMOUNT "/data/.kstuff_noautomount" +#define SHADOWMOUNTPLUS_DIR "/data/shadowmount" +#define SHADOWMOUNTPLUS_MANUAL_LIST "/data/shadowmount/manual.lst" + +static bool shadowmountplus_enabled(void) { + struct stat st; + return access(SHADOWMOUNTPLUS_NOAUTOMOUNT, F_OK) == 0 && + stat(SHADOWMOUNTPLUS_DIR, &st) == 0 && + S_ISDIR(st.st_mode); +} + +static int close_with_errno(FILE* f, int ret) { + int saved_errno = errno; + fclose(f); + errno = saved_errno; + return ret; +} + +static int add_shadowmountplus_link(const char* link_path) { + FILE* f = fopen(SHADOWMOUNTPLUS_MANUAL_LIST, "a+"); + if (!f) { + return -1; + } + + if (fseek(f, 0, SEEK_SET) != 0) { + return close_with_errno(f, -1); + } + + bool has_content = false; + bool ends_with_newline = true; + char line[PATH_MAX + 4]; + + while (fgets(line, sizeof(line), f)) { + size_t len = strlen(line); + has_content = true; + ends_with_newline = len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r'); + line[strcspn(line, "\r\n")] = '\0'; + + if (!strcmp(line, link_path)) { + fclose(f); + return 1; + } + } + + if (ferror(f) || fseek(f, 0, SEEK_END) != 0) { + return close_with_errno(f, -1); + } + + int ret = 0; + if (has_content && !ends_with_newline && fputc('\n', f) == EOF) { + ret = -1; + } + if (ret == 0 && fprintf(f, "%s\n", link_path) < 0) { + ret = -1; + } + if (fclose(f) != 0) { + ret = -1; + } + + return ret; +} + int main(void) { char cwd[PATH_MAX]; char title_id[32] = {}; @@ -31,13 +93,43 @@ int main(void) { notify("Dump Installer 1.05 Beta - PFS + UFS + exFAT"); + if (!getcwd(cwd, sizeof(cwd))) { + printf("Error: Unable to determine working directory\n"); + return -1; + } + + char image_file[MAX_PATH] = {}; + bool is_ufs = false; + bool is_pfs = false; + bool is_exfat = false; + bool has_image = find_image_in_dir(cwd, image_file, sizeof(image_file), + &is_ufs, &is_pfs, &is_exfat); + char mount_point[MAX_PATH] = {0}; + const char* nullfs_src = cwd; + + if (shadowmountplus_enabled()) { + const char* link_path = has_image ? image_file : cwd; + int ret = add_shadowmountplus_link(link_path); + if (ret == 1) { + notify("Game already installed in ShadowMountPlus: %s", link_path); + return 0; + } + if (ret != 0) { + notify("Failed to update ShadowMountPlus: %s", strerror(errno)); + return -1; + } + + notify("Added to ShadowMountPlus: %s", link_path); + return 0; + } + const char *dirs[] = { "/data/imgmnt", "/data/imgmnt/exfatmnt", "/data/imgmnt/pfsmnt", "/data/imgmnt/ufsmnt" }; - + for (size_t i = 0; i < sizeof(dirs)/sizeof(dirs[0]); i++) { if (mkdir(dirs[i], 0755) != 0) { if (errno != EEXIST) { @@ -45,7 +137,7 @@ int main(void) { char parent[PATH_MAX]; strncpy(parent, dirs[i], sizeof(parent) - 1); parent[sizeof(parent)-1] = '\0'; - + char *last_slash = strrchr(parent, '/'); if (last_slash && last_slash != parent) { *last_slash = '\0'; @@ -53,27 +145,13 @@ int main(void) { } if (mkdir(dirs[i], 0755) != 0 && errno != EEXIST) { - printf("Failed to create %s (errno %d: %s)\n", + printf("Failed to create %s (errno %d: %s)\n", dirs[i], errno, strerror(errno)); return 1; } } } } - - if (!getcwd(cwd, sizeof(cwd))) { - printf("Error: Unable to determine working directory\n"); - return -1; - } - - char image_file[MAX_PATH] = {}; - bool is_ufs = false; - bool is_pfs = false; - bool is_exfat = false; - bool has_image = find_image_in_dir(cwd, image_file, sizeof(image_file), - &is_ufs, &is_pfs, &is_exfat); - char mount_point[MAX_PATH] = {0}; - const char* nullfs_src = cwd; if (has_image) { if (is_ufs) {