Example #1
0
App appGetCiaInfo(const std::string file, MediaType mediaType) {
    if(!serviceRequire("am")) {
        return {};
    }

    FS_archive archive = (FS_archive) {ARCH_SDMC, (FS_path) {PATH_EMPTY, 1, (u8*) ""}};
    Result archiveResult = FSUSER_OpenArchive(NULL, &archive);
    if(archiveResult != 0) {
        platformSetError(serviceParseError((u32) archiveResult));
        return {};
    }

    Handle handle = 0;
    Result openResult = FSUSER_OpenFile(NULL, &handle, archive, FS_makePath(PATH_CHAR, file.c_str()), FS_OPEN_READ, FS_ATTRIBUTE_NONE);
    if(openResult != 0) {
        platformSetError(serviceParseError((u32) openResult));
        return {};
    }

    TitleList titleInfo;
    Result infoResult = AM_GetCiaFileInfo(appMediatypeToByte(mediaType), &titleInfo, handle);
    if(infoResult != 0) {
        platformSetError(serviceParseError((u32) infoResult));
        return {};
    }

    FSFILE_Close(handle);
    FSUSER_CloseArchive(NULL, &archive);

    App app;
    app.titleId = titleInfo.titleID;
    app.uniqueId = ((u32*) &titleInfo.titleID)[0];
    strcpy(app.productCode, "<N/A>");
    app.mediaType = mediaType;
    app.platform = appPlatformFromId(((u16*) &titleInfo.titleID)[3]);
    app.category = appCategoryFromId(((u16*) &titleInfo.titleID)[2]);
    app.version = titleInfo.titleVersion;
    app.size = titleInfo.size;
    return app;
}
Example #2
0
Result task_create_file_item(list_item** out, FS_Archive archive, const char* path) {
    Result res = 0;

    list_item* item = (list_item*) calloc(1, sizeof(list_item));
    if(item != NULL) {
        file_info* fileInfo = (file_info*) calloc(1, sizeof(file_info));
        if(fileInfo != NULL) {
            fileInfo->archive = archive;
            util_get_path_file(fileInfo->name, path, FILE_NAME_MAX);
            fileInfo->attributes = 0;

            fileInfo->size = 0;
            fileInfo->isCia = false;
            fileInfo->isTicket = false;

            if(util_is_dir(archive, path)) {
                item->color = COLOR_DIRECTORY;

                size_t len = strlen(path);
                if(len > 1 && path[len - 1] != '/') {
                    snprintf(fileInfo->path, FILE_PATH_MAX, "%s/", path);
                } else {
                    strncpy(fileInfo->path, path, FILE_PATH_MAX);
                }

                fileInfo->attributes = FS_ATTRIBUTE_DIRECTORY;
            } else {
                item->color = COLOR_FILE;

                strncpy(fileInfo->path, path, FILE_PATH_MAX);

                FS_Path* fileFsPath = util_make_path_utf8(fileInfo->path);
                if(fileFsPath != NULL) {
                    Handle fileHandle;
                    if(R_SUCCEEDED(FSUSER_OpenFile(&fileHandle, archive, *fileFsPath, FS_OPEN_READ, 0))) {
                        FSFILE_GetAttributes(fileHandle, &fileInfo->attributes);
                        FSFILE_GetSize(fileHandle, &fileInfo->size);

                        size_t len = strlen(fileInfo->path);
                        if(len > 4) {
                            if(strcasecmp(&fileInfo->path[len - 4], ".cia") == 0) {
                                AM_TitleEntry titleEntry;
                                if(R_SUCCEEDED(AM_GetCiaFileInfo(MEDIATYPE_SD, &titleEntry, fileHandle))) {
                                    fileInfo->isCia = true;
                                    fileInfo->ciaInfo.titleId = titleEntry.titleID;
                                    fileInfo->ciaInfo.version = titleEntry.version;
                                    fileInfo->ciaInfo.installedSize = titleEntry.size;
                                    fileInfo->ciaInfo.hasMeta = false;

                                    if((titleEntry.titleID & 0x0000801000000002) != 0 && R_SUCCEEDED(AM_GetCiaFileInfo(MEDIATYPE_NAND, &titleEntry, fileHandle))) {
                                        fileInfo->ciaInfo.installedSize = titleEntry.size;
                                    }

                                    SMDH* smdh = (SMDH*) calloc(1, sizeof(SMDH));
                                    if(smdh != NULL) {
                                        if(R_SUCCEEDED(util_get_cia_file_smdh(smdh, fileHandle))) {
                                            if(smdh->magic[0] == 'S' && smdh->magic[1] == 'M' && smdh->magic[2] == 'D' && smdh->magic[3] == 'H') {
                                                u8 systemLanguage = CFG_LANGUAGE_EN;
                                                CFGU_GetSystemLanguage(&systemLanguage);

                                                fileInfo->ciaInfo.hasMeta = true;
                                                utf16_to_utf8((uint8_t*) fileInfo->ciaInfo.meta.shortDescription, smdh->titles[systemLanguage].shortDescription, sizeof(fileInfo->ciaInfo.meta.shortDescription) - 1);
                                                utf16_to_utf8((uint8_t*) fileInfo->ciaInfo.meta.longDescription, smdh->titles[systemLanguage].longDescription, sizeof(fileInfo->ciaInfo.meta.longDescription) - 1);
                                                utf16_to_utf8((uint8_t*) fileInfo->ciaInfo.meta.publisher, smdh->titles[systemLanguage].publisher, sizeof(fileInfo->ciaInfo.meta.publisher) - 1);
                                                fileInfo->ciaInfo.meta.region = smdh->region;
                                                fileInfo->ciaInfo.meta.texture = screen_load_texture_tiled_auto(smdh->largeIcon, sizeof(smdh->largeIcon), 48, 48, GPU_RGB565, false);
                                            }
                                        }

                                        free(smdh);
                                    }
                                }
                            } else if(strcasecmp(&fileInfo->path[len - 4], ".tik") == 0) {
                                u32 bytesRead = 0;

                                u8 sigType = 0;
                                if(R_SUCCEEDED(FSFILE_Read(fileHandle, &bytesRead, 3, &sigType, sizeof(sigType))) && bytesRead == sizeof(sigType) && sigType <= 5) {
                                    static u32 dataOffsets[6] = {0x240, 0x140, 0x80, 0x240, 0x140, 0x80};
                                    static u32 titleIdOffset = 0x9C;

                                    u64 titleId = 0;
                                    if(R_SUCCEEDED(FSFILE_Read(fileHandle, &bytesRead, dataOffsets[sigType] + titleIdOffset, &titleId, sizeof(titleId))) && bytesRead == sizeof(titleId)) {
                                        fileInfo->isTicket = true;
                                        fileInfo->ticketInfo.titleId = __builtin_bswap64(titleId);
                                    }
                                }
                            }
                        }

                        FSFILE_Close(fileHandle);
                    }

                    util_free_path_utf8(fileFsPath);
                }
            }

            strncpy(item->name, fileInfo->name, LIST_ITEM_NAME_MAX);
            item->data = fileInfo;

            *out = item;
        } else {
            free(item);

            res = R_FBI_OUT_OF_MEMORY;
        }
    } else {
        res = R_FBI_OUT_OF_MEMORY;
    }

    return res;
}
Example #3
0
int exec_cia(const char* path, const char** args){
	struct stat sBuff;
	bool fileExists;
	bool inited;

	if(path == NULL || path[0] == '\0'){
		errno = EINVAL;
		return -1;
	}

	fileExists = stat(path, &sBuff) == 0;
	if(!fileExists){
		errno = ENOENT;
		return -1;
	}
	else if(S_ISDIR(sBuff.st_mode)){
		errno = EINVAL;;
		return -1;
	}

	inited = R_SUCCEEDED(amInit()) && R_SUCCEEDED(fsInit());
	if(inited){
		Result res;
		AM_TitleEntry ciaInfo;
		FS_Archive ciaArchive;
		Handle ciaFile;
		int ciaInstalled;
		ciaParam param;
		int argsLength;

		//open cia file
		res = FSUSER_OpenArchive(&ciaArchive, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, ""));
		if(R_FAILED(res))
			errorAndQuit("Cant open SD FS archive.");

		res = FSUSER_OpenFile(&ciaFile, ciaArchive, fsMakePath(PATH_ASCII, path + 5/*skip "sdmc:"*/), FS_OPEN_READ, 0);
		if(R_FAILED(res))
			errorAndQuit("Cant open CIA file.");

		res = AM_GetCiaFileInfo(MEDIATYPE_SD, &ciaInfo, ciaFile);
		if(R_FAILED(res))
			errorAndQuit("Cant get CIA file info.");

		ciaInstalled = isCiaInstalled(ciaInfo.titleID, ciaInfo.version);
		if(ciaInstalled == -1){
			//error
			errorAndQuit("Could not read title id list.");
		}
		else if(ciaInstalled == 0){
			//not installed
			int error = installCia(ciaFile);
			if(error == -1)
				errorAndQuit("Cant install CIA.");
		}

		FSFILE_Close(ciaFile);
		FSUSER_CloseArchive(ciaArchive);

		param.argc = 0;
		argsLength = 0;
		char* argLocation = param.args;
		while(args[param.argc] != NULL){
			strcpy(argLocation, args[param.argc]);
			argLocation += strlen(args[param.argc]) + 1;
			argsLength += strlen(args[param.argc]) + 1;
			param.argc++;
		}

		res = APT_PrepareToDoApplicationJump(0, ciaInfo.titleID, 0x1);
		if(R_FAILED(res))
			errorAndQuit("CIA cant run, cant prepare.");

		res = APT_DoApplicationJump(&param, sizeof(param.argc) + argsLength, argvHmac);
		if(R_FAILED(res))
			errorAndQuit("CIA cant run, cant jump.");

		//wait for application jump, for some reason its not instant
		while(1);
	}

	//should never be reached
	amExit();
	fsExit();
	errno = ENOTSUP;
	return -1;
}
Example #4
0
TitleList *getUpdateCIAs() {
  Handle dir, CIAFile;
  FS_DirectoryEntry ent;
  int ret;
  int ciafiles;
  TitleList *updateCIAs;
  char ciaPath[9 + 16 + 4 + 1]; // /updates/ + 16 hex digits + .cia + \0
  
  LOG_INFO("getUpdateCIAs");
  // Run through first and count .cia files.
  dir = openDirectory(CIAS_PATH);
  if(dir == 0) {
    LOG_ERROR("getUpdateCIAs: Failed to open SDMC:" CIAS_PATH ".\n");
    printf("Failed to open SDMC:" CIAS_PATH ".\n");
    goto error0;
  }
  ciafiles = 0;
  for(;;) {
    ret = getNextFile(dir, &ent);
    
    if(ret < 1) {
      if(ret == -1) {
        LOG_ERROR("getUpdateCIAs: Error reading directory.");
        printf("Error reading directory.\n");
        goto error2;
      }
      break;
    }
    
    simpleUTF16toASCII((char *)(ent.name));
    if(isCIAName((char *)(ent.name)) == 1) {
      ciafiles++;
    }
  }
  closeDirectory(dir);
  LOG_VERBOSE("Found %d files.", ciafiles);
  updateCIAs = initTitleList(ciafiles, 0);
  
  // Run through a second time and add CIA info.
  dir = openDirectory(CIAS_PATH);
  if(dir == 0) {
    LOG_ERROR("getUpdateCIAs: Failed to open SDMC:" CIAS_PATH ".\n");
    printf("Failed to open SDMC:" CIAS_PATH ".\n");
    goto error1;
  }
  ciafiles = 0;
  for(;;) {
    ret = getNextFile(dir, &ent);
    if(ret < 1) {
      if(ret == -1) {
        LOG_ERROR("getUpdateCIAs: Error reading directory.");
        printf("Error reading directory.\n");
        goto error2;
      }
      break;
    }
    
    simpleUTF16toASCII((char *)(ent.name));
    if(isCIAName((char *)(ent.name)) == 1) {
      snprintf(ciaPath, 9 + 16 + 4 + 1, CIAS_PATH "%s", ent.name);
      CIAFile = openFileHandle(ciaPath, FS_OPEN_READ);
      if(CIAFile == 0) {
        LOG_ERROR("getUpdateCIAs: Failed to open %s for read.\n", ciaPath);
        printf("Failed to open %s for read.\n", ciaPath);
        goto error2;
      }
      
      if(R_FAILED(AM_GetCiaFileInfo(MEDIATYPE_NAND, updateCIAs->title[ciafiles], CIAFile))) {
        LOG_ERROR("getUpdateCIAs: Failed to get information on %s.\n", ciaPath);
        printf("Failed to get information on %s.\n", ciaPath);
        goto error3;
      }
      
      closeFileHandle(CIAFile);
      
      ciafiles++;
      LOG_VERBOSE("getUpdateCIAs: Added %s.", (char *)(ent.name));
    }
  }
  closeDirectory(dir);
  
  LOG_INFO("getUpdateCIAs: Got CIAs from SD card.");
  return(updateCIAs);

error3:
  closeFileHandle(CIAFile);
error2:
  closeDirectory(dir);
error1:
  freeTitleList(updateCIAs);
error0:
  LOG_ERROR("getUpdateCIAs: Failed to get CIAs from SD card.");
  return(NULL);
}
Example #5
0
bool installTTP(char* path, u8 mediatype) { // Install a TTP file. (needs libzip and installCIA)

	Result res;
	FS_Archive archive = {ARCHIVE_SDMC, {PATH_EMPTY, 0, 0}};
	FSUSER_OpenArchive(&archive);
	FSUSER_DeleteDirectoryRecursively(archive, fsMakePath(PATH_ASCII, "/tmp/cias"));
	FSUSER_CreateDirectory(archive, fsMakePath(PATH_ASCII, "/tmp/cias"), 0);
	FILE* ttp = fopen(path, "rb");
	FILE* tmp = fopen("/tmp/cias/ttp.tmp", "wb");

	u32 titlesAmount;
	AM_GetTitleCount(mediatype, &titlesAmount);
	u64* titleIDs = malloc(sizeof(u64) * titlesAmount);
	AM_GetTitleIdList(mediatype, titlesAmount, titleIDs);

	u32 size;
	fseek(ttp, 0x19, SEEK_SET);
	fread(&size, 0x4, 1, ttp);
	fseek(ttp, 0x1D, SEEK_SET);

	u32 blockAmount = size / 0x160000; // Finds how many blocks of 4MB you have in the file
	u32 i;
	char* block = malloc(0x160000);
	for (i = 0; i < blockAmount; i++) {
		fread(block, 1, 0x160000, ttp);
		fwrite(block, 1, 0x160000, tmp);
	}

	if (size % 0x160000 != 0) {
		fread(block, 1, size-0x160000*blockAmount, ttp);
		fwrite(block, 1, size-0x160000*blockAmount, tmp);
	}

	free(block);

	fclose(ttp);
	fclose(tmp);

	FSUSER_DeleteDirectoryRecursively(archive, fsMakePath(PATH_ASCII, "/tmp/cias"));
	FSUSER_CreateDirectory(archive, fsMakePath(PATH_ASCII, "/tmp/cias"), 0);

	Zip *zipHandle = ZipOpen("/tmp/cias/ttp.tmp");
	ZipExtract(zipHandle, NULL);
	ZipClose(zipHandle);

	Handle ciaDir;
	FS_Archive fsarchive;
	u32 actualAmount;
	FS_DirectoryEntry* entries;

	FSUSER_DeleteFile(archive, fsMakePath(PATH_ASCII, "/tmp/cias/ttp.tmp"));
	res = FSUSER_OpenDirectory(&ciaDir, fsarchive, fsMakePath(PATH_ASCII, "/tmp/cias"));
	if (res != 0) { free(titleIDs); return false; }
	entries = malloc(256 * sizeof(FS_DirectoryEntry));
	res = FSDIR_Read(ciaDir, &actualAmount, 256, entries);
	if (res != 0) { free(titleIDs); return false; }

	char* ciaPath;
	Handle ciaFileHandle;
	AM_TitleEntry ciaInfo;
	for (i = 0; i < actualAmount; i++) {
		ciaPath = malloc(14 + strlen(entries[i].shortName));
		strcpy(ciaPath, "/tmp/cias/");
		strcat(ciaPath, entries[i].shortName);
		strcat(ciaPath, ".cia");
		
		FSUSER_OpenFile(&ciaFileHandle, archive, fsMakePath(PATH_ASCII, ciaPath), FS_OPEN_READ, 0);
		AM_GetCiaFileInfo(mediatype, &ciaInfo, ciaFileHandle);
		FSFILE_Close(ciaFileHandle);
		
		if (ciaInfo.titleID == 0x0004013800000002LL || ciaInfo.titleID == 0x0004013820000002LL) {
			if (!installCIA(ciaPath, mediatype, titleIDs, entries[i].shortName))
				if (!installCIA(ciaPath, mediatype, titleIDs, entries[i].shortName)) // Tries to install the CIA 3 times then give up. If it has to give up, that probably means brick.
					if (!installCIA(ciaPath, mediatype, titleIDs, entries[i].shortName))
						return false;

			break;
		}
		free(ciaPath);
	}

	for (i = 0; i < actualAmount; i++) {
		ciaPath = malloc(14 + strlen(entries[i].shortName));
		strcpy(ciaPath, "/tmp/cias/");
		strcat(ciaPath, entries[i].shortName);
		strcat(ciaPath, ".cia");
		if (!installCIA(ciaPath, mediatype, titleIDs, entries[i].shortName))
			if (!installCIA(ciaPath, mediatype, titleIDs, entries[i].shortName)) // Tries to install the CIA 3 times then give up. If it has to give up, that probably means brick.
				installCIA(ciaPath, mediatype, titleIDs, entries[i].shortName);

		free(ciaPath);
	}

	FSUSER_DeleteDirectoryRecursively(archive, fsMakePath(PATH_ASCII, "/tmp/cias"));

	FSUSER_CloseArchive(&archive);

	free(titleIDs);

	return true;

}