mirror of
				https://github.com/Atmosphere-NX/Atmosphere-libs.git
				synced 2025-10-31 03:25:47 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			152 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			152 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) Atmosphère-NX
 | |
|  *
 | |
|  * This program is free software; you can redistribute it and/or modify it
 | |
|  * under the terms and conditions of the GNU General Public License,
 | |
|  * version 2, as published by the Free Software Foundation.
 | |
|  *
 | |
|  * This program is distributed in the hope it will be useful, but WITHOUT
 | |
|  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | |
|  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | |
|  * more details.
 | |
|  *
 | |
|  * You should have received a copy of the GNU General Public License
 | |
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | |
|  */
 | |
| #include <stratosphere.hpp>
 | |
| 
 | |
| namespace ams::ncm {
 | |
| 
 | |
|     PackageSystemUpdateTask::~PackageSystemUpdateTask() {
 | |
|         if (m_context_path.GetLength() > 0) {
 | |
|             fs::DeleteFile(m_context_path);
 | |
|         }
 | |
|         this->Inactivate();
 | |
|     }
 | |
| 
 | |
|     void PackageSystemUpdateTask::Inactivate() {
 | |
|         if (m_gamecard_content_meta_database_active) {
 | |
|             InactivateContentMetaDatabase(StorageId::GameCard);
 | |
|             m_gamecard_content_meta_database_active = false;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     Result PackageSystemUpdateTask::Initialize(const char *package_root, const char *context_path, void *buffer, size_t buffer_size, bool requires_exfat_driver, FirmwareVariationId firmware_variation_id) {
 | |
|         /* Set the firmware variation id. */
 | |
|         this->SetFirmwareVariationId(firmware_variation_id);
 | |
| 
 | |
|         /* Activate the game card content meta database. */
 | |
|         R_TRY(ActivateContentMetaDatabase(StorageId::GameCard));
 | |
|         m_gamecard_content_meta_database_active = true;
 | |
|         auto meta_db_guard = SCOPE_GUARD { this->Inactivate(); };
 | |
| 
 | |
|         /* Open the game card content meta database. */
 | |
|         OpenContentMetaDatabase(std::addressof(m_package_db), StorageId::GameCard);
 | |
| 
 | |
|         ContentMetaDatabaseBuilder builder(std::addressof(m_package_db));
 | |
| 
 | |
|         /* Cleanup and build the content meta database. */
 | |
|         R_TRY(builder.Cleanup());
 | |
|         R_TRY(builder.BuildFromPackage(package_root));
 | |
| 
 | |
|         /* Create a new context file. */
 | |
|         fs::DeleteFile(context_path);
 | |
|         R_TRY(FileInstallTaskData::Create(context_path, GameCardMaxContentMetaCount));
 | |
|         auto context_guard = SCOPE_GUARD { fs::DeleteFile(context_path); };
 | |
| 
 | |
|         /* Initialize data. */
 | |
|         R_TRY(m_data.Initialize(context_path));
 | |
| 
 | |
|         /* Initialize PackageInstallTaskBase. */
 | |
|         u32 config = !requires_exfat_driver ? InstallConfig_SystemUpdate : InstallConfig_SystemUpdate | InstallConfig_RequiresExFatDriver;
 | |
|         R_TRY(PackageInstallTaskBase::Initialize(package_root, buffer, buffer_size, StorageId::BuiltInSystem, std::addressof(m_data), config));
 | |
| 
 | |
|         /* Cancel guards. */
 | |
|         context_guard.Cancel();
 | |
|         meta_db_guard.Cancel();
 | |
| 
 | |
|         /* Set the context path. */
 | |
|         m_context_path.Assign(context_path);
 | |
|         R_SUCCEED();
 | |
|     }
 | |
| 
 | |
|     util::optional<ContentMetaKey> PackageSystemUpdateTask::GetSystemUpdateMetaKey() {
 | |
|         StorageContentMetaKey storage_keys[0x10];
 | |
|         s32 ofs = 0;
 | |
| 
 | |
|         s32 count = 0;
 | |
|         do {
 | |
|             /* List content meta keys. */
 | |
|             if (R_FAILED(this->ListContentMetaKey(std::addressof(count), storage_keys, util::size(storage_keys), ofs, ListContentMetaKeyFilter::All))) {
 | |
|                 break;
 | |
|             }
 | |
| 
 | |
|             /* Add listed keys to the offset. */
 | |
|             ofs += count;
 | |
| 
 | |
|             /* Check if any of these keys are for a SystemUpdate. */
 | |
|             for (s32 i = 0; i < count; i++) {
 | |
|                 const ContentMetaKey &key = storage_keys[i].key;
 | |
|                 if (key.type == ContentMetaType::SystemUpdate) {
 | |
|                     return key;
 | |
|                 }
 | |
|             }
 | |
|         } while (count > 0);
 | |
| 
 | |
|         return util::nullopt;
 | |
|     }
 | |
| 
 | |
|     Result PackageSystemUpdateTask::GetInstallContentMetaInfo(InstallContentMetaInfo *out, const ContentMetaKey &key) {
 | |
|         /* Get the content info for the key. */
 | |
|         ContentInfo info;
 | |
|         R_TRY(this->GetContentInfoOfContentMeta(std::addressof(info), key));
 | |
| 
 | |
|         /* Create a new install content meta info. */
 | |
|         *out = InstallContentMetaInfo::MakeUnverifiable(info.GetId(), info.GetSize(), key);
 | |
|         R_SUCCEED();
 | |
|     }
 | |
| 
 | |
|     Result PackageSystemUpdateTask::PrepareInstallContentMetaData() {
 | |
|         /* Obtain a SystemUpdate key. */
 | |
|         ContentMetaKey key;
 | |
|         auto list_count = m_package_db.ListContentMeta(std::addressof(key), 1, ContentMetaType::SystemUpdate);
 | |
|         R_UNLESS(list_count.written > 0, ncm::ResultSystemUpdateNotFoundInPackage());
 | |
| 
 | |
|         /* Get the content info for the key. */
 | |
|         ContentInfo info;
 | |
|         R_TRY(this->GetContentInfoOfContentMeta(std::addressof(info), key));
 | |
| 
 | |
|         /* Prepare the content meta. */
 | |
|         R_RETURN(this->PrepareContentMeta(InstallContentMetaInfo::MakeUnverifiable(info.GetId(), info.GetSize(), key), key, util::nullopt));
 | |
|     }
 | |
| 
 | |
|     Result PackageSystemUpdateTask::PrepareDependency() {
 | |
|         R_RETURN(this->PrepareSystemUpdateDependency());
 | |
|     }
 | |
| 
 | |
|     Result PackageSystemUpdateTask::GetContentInfoOfContentMeta(ContentInfo *out, const ContentMetaKey &key) {
 | |
|         s32 ofs = 0;
 | |
|         while (true) {
 | |
|             /* List content infos. */
 | |
|             s32 count;
 | |
|             ContentInfo info;
 | |
|             R_TRY(m_package_db.ListContentInfo(std::addressof(count), std::addressof(info), 1, key, ofs++));
 | |
| 
 | |
|             /* No content infos left to list. */
 | |
|             if (count == 0) {
 | |
|                 break;
 | |
|             }
 | |
| 
 | |
|             /* Check if the info is for meta content. */
 | |
|             if (info.GetType() == ContentType::Meta) {
 | |
|                 *out = info;
 | |
|                 R_SUCCEED();
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /* Not found. */
 | |
|         R_THROW(ncm::ResultContentInfoNotFound());
 | |
|     }
 | |
| 
 | |
| }
 |