ncm.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  1. #include <stdio.h>
  2. #include <stdint.h>
  3. #include <stdbool.h>
  4. #include <stdarg.h>
  5. #include <switch.h>
  6. #include "nx/ncm.h"
  7. #include "util/log.h"
  8. bool ncm_init(void)
  9. {
  10. Result rc = ncmInitialize();
  11. if (R_FAILED(rc))
  12. {
  13. write_log("Failed to init ncm\n");
  14. return false;
  15. }
  16. return true;
  17. }
  18. void ncm_exit(void)
  19. {
  20. ncmExit();
  21. }
  22. bool ncm_open_storage(NcmContentStorage *cs, NcmStorageId storage_id)
  23. {
  24. if (!cs)
  25. {
  26. write_log("missing params in ncm_open_storage\n");
  27. return false;
  28. }
  29. Result rc = ncmOpenContentStorage(cs, storage_id);
  30. if (R_FAILED(rc))
  31. {
  32. write_log("failed to open content storage\n");
  33. return false;
  34. }
  35. return true;
  36. }
  37. bool ncm_check_if_placeholder_id_exists(NcmContentStorage *cs, const NcmPlaceHolderId *placeholder_id)
  38. {
  39. if (!cs || !placeholder_id)
  40. {
  41. write_log("missing params in ncm_check_if_placeholder_exists\n");
  42. return false;
  43. }
  44. bool exists_out = false;
  45. if (R_FAILED(ncmContentStorageHasPlaceHolder(cs, &exists_out, placeholder_id)))
  46. {
  47. write_log("failed to check if placeholder_id exists\n");
  48. return false;
  49. }
  50. return exists_out;
  51. }
  52. bool ncm_generate_placeholder_id(NcmContentStorage *cs, NcmPlaceHolderId *placeholder_id)
  53. {
  54. if (!cs || !placeholder_id)
  55. {
  56. write_log("missing params in ncm_generate_placeholder\n");
  57. return false;
  58. }
  59. Result rc = ncmContentStorageGeneratePlaceHolderId(cs, placeholder_id);
  60. if (R_FAILED(rc))
  61. {
  62. write_log("failed to generate placeholder_id ID\n");
  63. return false;
  64. }
  65. return true;
  66. }
  67. bool ncm_create_placeholder_id(NcmContentStorage *cs, const NcmContentId *content_id, const NcmPlaceHolderId *placeholder_id, int64_t size)
  68. {
  69. if (!cs || !placeholder_id || !content_id)
  70. {
  71. write_log("missing params in ncm_create_placeholder\n");
  72. return false;
  73. }
  74. Result rc = ncmContentStorageCreatePlaceHolder(cs, content_id, placeholder_id, size);
  75. if (R_FAILED(rc))
  76. {
  77. write_log("failed to create placeholder_id\n");
  78. return false;
  79. }
  80. return true;
  81. }
  82. bool ncm_get_placeholder_id_path(NcmContentStorage *cs, const NcmPlaceHolderId *placeholder_id, char *out_path, size_t size)
  83. {
  84. if (!cs || !placeholder_id || !out_path || !size)
  85. {
  86. write_log("missing params in ncm_get_placeholder_path\n");
  87. return false;
  88. }
  89. Result rc = ncmContentStorageGetPlaceHolderPath(cs, out_path, size, placeholder_id);
  90. if (R_FAILED(rc))
  91. {
  92. write_log("failed to get placeholder_id path\n");
  93. return false;
  94. }
  95. return true;
  96. }
  97. bool ncm_write_placeholder_id(NcmContentStorage *cs, const NcmPlaceHolderId *placeholder_id, uint64_t offset, const void *data, size_t data_size)
  98. {
  99. if (!cs || !placeholder_id || !data || !data_size)
  100. {
  101. write_log("missing params in ncm_write_placeholder\n");
  102. return false;
  103. }
  104. Result rc = ncmContentStorageWritePlaceHolder(cs, placeholder_id, offset, data, data_size);
  105. if (R_FAILED(rc))
  106. {
  107. write_log("failed to write to placeholder_id\n");
  108. return false;
  109. }
  110. return true;
  111. }
  112. bool ncm_delete_placeholder_id(NcmContentStorage *cs, const NcmPlaceHolderId *placeholder_id)
  113. {
  114. if (!cs || !placeholder_id)
  115. {
  116. write_log("missing params in ncm_delete_placeholder\n");
  117. return false;
  118. }
  119. Result rc = ncmContentStorageDeletePlaceHolder(cs, placeholder_id);
  120. if (R_FAILED(rc))
  121. {
  122. write_log("failed to delete placeholder_id\n");
  123. return false;
  124. }
  125. return true;
  126. }
  127. void ncm_delete_all_placeholders_id(void)
  128. {
  129. NcmContentStorage sd_storage = {0};
  130. if (ncm_open_storage(&sd_storage, NcmStorageId_SdCard))
  131. {
  132. if (R_FAILED(ncmContentStorageCleanupAllPlaceHolder(&sd_storage)))
  133. {
  134. write_log("failed to delete all placeholder_id from sd card\n");
  135. }
  136. ncm_close_storage(&sd_storage);
  137. }
  138. NcmContentStorage nand_storage = {0};
  139. if (ncm_open_storage(&nand_storage, NcmStorageId_BuiltInUser))
  140. {
  141. if (R_FAILED(ncmContentStorageCleanupAllPlaceHolder(&nand_storage)))
  142. {
  143. write_log("failed to delete all placeholder_id from nand\n");
  144. }
  145. ncm_close_storage(&nand_storage);
  146. }
  147. }
  148. bool ncm_register_placeholder_id(NcmContentStorage *cs, const NcmContentId *content_id, const NcmPlaceHolderId *placeholder_id)
  149. {
  150. if (!cs || !placeholder_id || !placeholder_id)
  151. {
  152. write_log("missing params in ncm_generate_placeholder\n");
  153. return false;
  154. }
  155. Result rc = ncmContentStorageRegister(cs, content_id, placeholder_id);
  156. if (R_FAILED(rc))
  157. {
  158. write_log("failed to register placeholder_id\n");
  159. return false;
  160. }
  161. return true;
  162. }
  163. bool ncm_check_if_content_id_exists(NcmContentStorage *cs, const NcmContentId *content_id)
  164. {
  165. if (!cs || !content_id)
  166. {
  167. write_log("missing params in ncm_check_if_content_id_exists\n");
  168. return false;
  169. }
  170. bool exist_out = 0;
  171. Result rc = ncmContentStorageHas(cs, &exist_out, content_id);
  172. if (R_FAILED(rc))
  173. {
  174. write_log("failed to check if nca exists\n");
  175. return false;
  176. }
  177. return exist_out;
  178. }
  179. bool ncm_delete_content_id(NcmContentStorage *cs, const NcmContentId *content_id)
  180. {
  181. if (!cs || !content_id)
  182. {
  183. write_log("missing params in ncm_delete_content_id\n");
  184. return false;
  185. }
  186. Result rc = ncmContentStorageDelete(cs, content_id);
  187. if (R_FAILED(rc))
  188. {
  189. write_log("failed to delete nca\n");
  190. return false;
  191. }
  192. return true;
  193. }
  194. bool ncm_get_content_id_path(NcmContentStorage *cs, char *path_out, size_t size, const NcmContentId *content_id)
  195. {
  196. if (!cs || !content_id || !path_out || !size)
  197. {
  198. write_log("missing params in ncm_get_content_id_path\n");
  199. return false;
  200. }
  201. Result rc = ncmContentStorageGetPath(cs, path_out, size, content_id);
  202. if (R_FAILED(rc))
  203. {
  204. write_log("failed to get storage path\n");
  205. return false;
  206. }
  207. return true;
  208. }
  209. int64_t ncm_get_placeholder_id_size(NcmContentStorage *cs, const NcmPlaceHolderId *placeholder_id)
  210. {
  211. if (!cs || !placeholder_id)
  212. {
  213. write_log("missing params in ncm_get_size_of_placeholder_id\n");
  214. return false;
  215. }
  216. int64_t size = 0;
  217. Result rc = ncmContentStorageGetSizeFromPlaceHolderId(cs, &size, placeholder_id);
  218. if (R_FAILED(rc))
  219. {
  220. write_log("failed to get size of placeholder_id\n");
  221. return 0;
  222. }
  223. return size;
  224. }
  225. int64_t ncm_get_content_id_size(NcmContentStorage *cs, const NcmContentId *content_id)
  226. {
  227. if (!cs || !content_id)
  228. {
  229. write_log("missing params in ncm_get_size_of_content_id\n");
  230. return 0;
  231. }
  232. int64_t size = 0;
  233. Result rc = ncmContentStorageGetSizeFromContentId(cs, &size, content_id);
  234. if (R_FAILED(rc))
  235. {
  236. write_log("failed to get size of nca\n");
  237. return 0;
  238. }
  239. return size;
  240. }
  241. bool ncm_read_content_id(NcmContentStorage *cs, void *data, size_t data_size, uint64_t offset, const NcmContentId *content_id)
  242. {
  243. Result rc = ncmContentStorageReadContentIdFile(cs, data, data_size, content_id, offset);
  244. if (R_FAILED(rc))
  245. {
  246. write_log("failed to read data from the nca\n");
  247. return false;
  248. }
  249. return true;
  250. }
  251. void ncm_close_storage(NcmContentStorage *cs)
  252. {
  253. ncmContentStorageClose(cs);
  254. serviceClose(&cs->s);
  255. }
  256. bool ncm_open_database(NcmContentMetaDatabase *db, NcmStorageId storage_id)
  257. {
  258. Result rc = ncmOpenContentMetaDatabase(db, storage_id);
  259. if (R_FAILED(rc))
  260. {
  261. write_log("failed to open database\n");
  262. return false;
  263. }
  264. return true;
  265. }
  266. bool ncm_set_database(NcmContentMetaDatabase *db, const NcmContentMetaKey *key, const void *data, size_t data_size)
  267. {
  268. Result rc = ncmContentMetaDatabaseSet(db, key, data, data_size);
  269. if (R_FAILED(rc))
  270. {
  271. write_log("failed to set meta database\n");
  272. return false;
  273. }
  274. return true;
  275. }
  276. bool ncm_commit_database(NcmContentMetaDatabase *db)
  277. {
  278. Result rc = ncmContentMetaDatabaseCommit(db);
  279. if (R_FAILED(rc))
  280. {
  281. write_log("failed to commit database\n");
  282. return false;
  283. }
  284. return true;
  285. }
  286. void ncm_close_database(NcmContentMetaDatabase *db)
  287. {
  288. ncmContentMetaDatabaseClose(db);
  289. serviceClose(&db->s);
  290. }
  291. int64_t ncm_get_storage_free_space(NcmStorageId storage_id)
  292. {
  293. int64_t size = 0;
  294. NcmContentStorage cs = {0};
  295. if (!ncm_open_storage(&cs, storage_id))
  296. {
  297. return 0;
  298. }
  299. if (R_FAILED(ncmContentStorageGetFreeSpaceSize(&cs, &size)))
  300. {
  301. write_log("failed to get free storage space\n");
  302. return 0;
  303. }
  304. ncm_close_storage(&cs);
  305. return size;
  306. }
  307. int64_t ncm_get_storage_total_size(NcmStorageId storage_id)
  308. {
  309. int64_t size = 0;
  310. NcmContentStorage cs = {0};
  311. if (!ncm_open_storage(&cs, storage_id))
  312. {
  313. return size;
  314. }
  315. if (R_FAILED(ncmContentStorageGetTotalSpaceSize(&cs, &size)))
  316. {
  317. write_log("failed to get total storage space\n");
  318. return 0;
  319. }
  320. ncm_close_storage(&cs);
  321. return size;
  322. }
  323. int32_t ncm_get_application_meta_total(NcmContentMetaDatabase *db, NcmContentMetaType type)
  324. {
  325. int32_t total = 0;
  326. int32_t written = 0;
  327. NcmApplicationContentMetaKey key = {0};
  328. Result rc = ncmContentMetaDatabaseListApplication(db, &total, &written, &key, 1, type);
  329. if (R_FAILED(rc))
  330. {
  331. write_log("Failed to get appliaction meta total. type: %s\n", ncm_get_meta_type_string(type));
  332. return 0;
  333. }
  334. return total;
  335. }
  336. int32_t ncm_get_meta_total(NcmContentMetaDatabase *db, NcmContentMetaType type)
  337. {
  338. int32_t total = 0;
  339. int32_t written = 0;
  340. NcmContentMetaKey key = {0};
  341. Result rc = ncmContentMetaDatabaseList(db, &total, &written, &key, 1, type, 0, 0, UINT64_MAX, NcmContentInstallType_Full);
  342. if (R_FAILED(rc))
  343. {
  344. write_log("Failed to get meta total. type: %s\n", ncm_get_meta_type_string(type));
  345. return 0;
  346. }
  347. return total;
  348. }
  349. bool ncm_get_latest_key(NcmContentMetaDatabase *db, NcmContentMetaKey *key_out, uint64_t id)
  350. {
  351. if (!db || !key_out || !id)
  352. {
  353. write_log("missing params in %s\n", __func__);
  354. return false;
  355. }
  356. Result rc = ncmContentMetaDatabaseGetLatestContentMetaKey(db, key_out, id);
  357. if (rc == 3589) // none found, not an error. still return false because no key.
  358. {
  359. write_log("no latest key found for id: %lX\n", id);
  360. return false;
  361. }
  362. if (R_FAILED(rc))
  363. {
  364. write_log("failed to get latest key\n");
  365. return false;
  366. }
  367. return true;
  368. }
  369. bool ncm_get_latest_key2(NcmContentMetaKey *out_key, uint64_t id) // temp name
  370. {
  371. if (!id)
  372. {
  373. write_log("missing params in %s\n", __func__);
  374. return 1;
  375. }
  376. // vars
  377. NcmContentMetaDatabase db_user = {0};
  378. NcmContentMetaDatabase db_sdcard = {0};
  379. NcmContentMetaKey key_user = {0};
  380. NcmContentMetaKey key_sdcard = {0};
  381. // open both storage.
  382. ncm_open_database(&db_user, NcmStorageId_BuiltInUser);
  383. ncm_open_database(&db_sdcard, NcmStorageId_SdCard);
  384. // first we try to find it in user, the sdcard.
  385. write_log("trying nand\n");
  386. bool has_user = ncm_get_latest_key(&db_user, &key_user, id);
  387. write_log("trying sd\n");
  388. bool has_sdcard = ncm_get_latest_key(&db_sdcard, &key_sdcard, id);
  389. // now close.
  390. ncm_close_database(&db_user);
  391. ncm_close_database(&db_sdcard);
  392. // check if any was found.
  393. if (!has_user && !has_sdcard)
  394. {
  395. return false;
  396. }
  397. // If theres 2 versions (ie. 2 updates exist because they were installed by bad installers), pick the highest value.
  398. if (has_user && has_sdcard)
  399. {
  400. write_log("found meta key id: %lx on sdcard and nand\n", id);
  401. // select highest versions
  402. if (key_user.version > key_sdcard.version)
  403. {
  404. *out_key = key_user;
  405. return true;
  406. }
  407. else
  408. {
  409. *out_key = key_sdcard;
  410. return true;
  411. }
  412. }
  413. if (has_user)
  414. {
  415. *out_key = key_user;
  416. return true;
  417. }
  418. else
  419. {
  420. *out_key = key_sdcard;
  421. return true;
  422. }
  423. }
  424. bool ncm_is_key_newer(const NcmContentMetaKey *key)
  425. {
  426. NcmContentMetaKey key_out = {0};
  427. // if it couldnt find a key, its newer.
  428. if (!ncm_get_latest_key2(&key_out, key->id))
  429. {
  430. return true;
  431. }
  432. write_log("new: %u installed: %u\n", key->version, key_out.version);
  433. return key->version >= key_out.version;
  434. }
  435. bool ncm_get_version(uint32_t version, uint8_t *major, uint8_t *minor, uint8_t *macro)
  436. {
  437. if (!version || !major || !minor || !macro)
  438. {
  439. write_log ("Missing params in %s\n", __func__);
  440. return false;
  441. }
  442. *major = (uint8_t)((version >> 26) & 0x3F);
  443. *minor = (uint8_t)((version >> 20) & 0x3F);
  444. *macro = (uint8_t)((version >> 16) & 0xF);
  445. return true;
  446. }
  447. void ncm_get_version_string(uint32_t version, NcmVersionString_t *out)
  448. {
  449. sprintf(out->major, "%u", (version >> 26) & 0x3F);
  450. sprintf(out->minor, "%u", (version >> 20) & 0x3F);
  451. sprintf(out->macro, "%u", (version >> 16) & 0xF);
  452. sprintf(out->bug_fix, "%u", (uint16_t)version);
  453. }
  454. #include <string.h>
  455. size_t ncm_calculate_content_info_size(const NcmContentInfo *info)
  456. {
  457. if (!info)
  458. {
  459. write_log("missing params in %s\n", __func__);
  460. return 0;
  461. }
  462. size_t size = 0;
  463. ncmContentInfoSizeToU64(info, &size);
  464. return size;
  465. }
  466. size_t ncm_calculate_content_infos_size(const NcmContentInfo *infos, uint16_t count)
  467. {
  468. if (!infos || !count)
  469. {
  470. write_log("missing params in %s\n", __func__);
  471. return 0;
  472. }
  473. size_t size = 0;
  474. for (uint16_t i = 0; i < count; i++)
  475. {
  476. size_t tmp_size = 0;
  477. if (!(tmp_size = ncm_calculate_content_info_size(&infos[i])))
  478. {
  479. return 0;
  480. }
  481. size += tmp_size;
  482. }
  483. return size;
  484. }
  485. bool ncm_get_content_type_from_infos(NcmContentInfo *infos, uint16_t count, NcmContentInfo *found, NcmContentType wanted_type)
  486. {
  487. if (!infos || !count || !found)
  488. {
  489. write_log("missing params in %s\n", __func__);
  490. return false;
  491. }
  492. for (uint16_t i = 0; i < count; i++)
  493. {
  494. if (infos[i].content_type == wanted_type)
  495. {
  496. *found = infos[i];
  497. return true;
  498. }
  499. }
  500. return false;
  501. }
  502. uint64_t ncm_get_app_id_from_title_id(uint64_t title_id, NcmContentMetaType type)
  503. {
  504. switch (type)
  505. {
  506. case NcmContentMetaType_SystemProgram:
  507. return title_id;
  508. case NcmContentMetaType_SystemData:
  509. return title_id;
  510. case NcmContentMetaType_SystemUpdate:
  511. return title_id;
  512. case NcmContentMetaType_BootImagePackage:
  513. return title_id;
  514. case NcmContentMetaType_BootImagePackageSafe:
  515. return title_id;
  516. case NcmContentMetaType_Application:
  517. return title_id;
  518. case NcmContentMetaType_Patch:
  519. return title_id ^ 0x800;
  520. case NcmContentMetaType_AddOnContent:
  521. return (title_id ^ 0x1000) & ~0xFFF;
  522. default:
  523. return 0;
  524. }
  525. }
  526. const char *ncm_get_storage_id_string(NcmStorageId storage_id)
  527. {
  528. switch (storage_id)
  529. {
  530. case NcmStorageId_None:
  531. return "None";
  532. case NcmStorageId_Host:
  533. return "Host";
  534. case NcmStorageId_GameCard:
  535. return "GameCard";
  536. case NcmStorageId_BuiltInSystem:
  537. return "BuildInSystem";
  538. case NcmStorageId_BuiltInUser:
  539. return "BuiltInUser";
  540. case NcmStorageId_SdCard:
  541. return "SdCard";
  542. case NcmStorageId_Any:
  543. return "Any";
  544. default:
  545. return "NULL";
  546. }
  547. }
  548. const char *ncm_get_meta_type_string(NcmContentMetaType type)
  549. {
  550. switch (type)
  551. {
  552. case NcmContentMetaType_SystemProgram:
  553. return "SystemProgram";
  554. case NcmContentMetaType_SystemData:
  555. return "SystemData";
  556. case NcmContentMetaType_SystemUpdate:
  557. return "SystemUpdate";
  558. case NcmContentMetaType_BootImagePackage:
  559. return "BootImagePackage";
  560. case NcmContentMetaType_BootImagePackageSafe:
  561. return "BootImagePackageSafe";
  562. case NcmContentMetaType_Application:
  563. return "Application";
  564. case NcmContentMetaType_Patch:
  565. return "Patch";
  566. case NcmContentMetaType_AddOnContent:
  567. return "AddOnContent";
  568. case NcmContentMetaType_Delta:
  569. return "Delta";
  570. default:
  571. return "NULL";
  572. }
  573. }
  574. const char *ncm_get_content_type_string(NcmContentType type)
  575. {
  576. switch (type)
  577. {
  578. case NcmContentType_Meta:
  579. return "Meta";
  580. case NcmContentType_Program:
  581. return "Program";
  582. case NcmContentType_Data:
  583. return "Data";
  584. case NcmContentType_Control:
  585. return "Control";
  586. case NcmContentType_HtmlDocument:
  587. return "HtmlDocument";
  588. case NcmContentType_LegalInformation:
  589. return "LegalInformation";
  590. case NcmContentType_DeltaFragment:
  591. return "DeltaFragment";
  592. default:
  593. return "NULL";
  594. }
  595. }
  596. const char *ncm_get_attribute_string(NcmContentMetaAttribute attribute)
  597. {
  598. switch (attribute)
  599. {
  600. case NcmContentMetaAttribute_None:
  601. return "None";
  602. case NcmContentMetaAttribute_IncludesExFatDriver:
  603. return "IncludesExFatDriver";
  604. case NcmContentMetaAttribute_Rebootless:
  605. return "Rebootless";
  606. default:
  607. return "NULL";
  608. }
  609. }
  610. const char *ncm_get_install_type_string(NcmContentInstallType type)
  611. {
  612. switch (type)
  613. {
  614. case NcmContentInstallType_Full:
  615. return "Full";
  616. case NcmContentInstallType_FragmentOnly:
  617. return "FragmentOnly";
  618. case NcmContentInstallType_Unknown:
  619. return "Unknown";
  620. default:
  621. return "NULL";
  622. }
  623. }
  624. /*
  625. * Debug
  626. */
  627. void ncm_print_key(const NcmContentMetaKey *key)
  628. {
  629. #ifdef DEBUG
  630. if (!key)
  631. {
  632. write_log("missing params in %s\n", __func__);
  633. return;
  634. }
  635. write_log("\nncm key print\n");
  636. write_log("id: %lX\n", key->id);
  637. write_log("title_version: %u\n", key->version);
  638. write_log("meta_type: %s\n", ncm_get_meta_type_string(key->type));
  639. write_log("install_type: %s\n", ncm_get_install_type_string(key->install_type));
  640. #endif
  641. }
  642. void ncm_print_keys(const NcmContentMetaKey *key, uint16_t count)
  643. {
  644. #ifdef DEBUG
  645. if (!key || !count)
  646. {
  647. write_log("missing params in %s\n", __func__);
  648. return;
  649. }
  650. for (uint16_t i = 0; i < count; i++)
  651. {
  652. ncm_print_key(&key[i]);
  653. }
  654. #endif
  655. }
  656. void ncm_print_application_record(const NcmContentStorageRecord *record)
  657. {
  658. #ifdef DEBUG
  659. if (!record)
  660. {
  661. write_log("missing params in %s\n", __func__);
  662. return;
  663. }
  664. write_log("\napplication_record\n");
  665. write_log("id %lX\n", record->key.id);
  666. write_log("version: %u\n", record->key.version);
  667. write_log("meta_type: %s\n", ncm_get_meta_type_string(record->key.type));
  668. write_log("install_type: %s\n", ncm_get_install_type_string(record->key.install_type));
  669. write_log("storage_id: %s\n", ncm_get_storage_id_string(record->storage_id));
  670. #endif
  671. }
  672. void ncm_print_application_records(const NcmContentStorageRecord *records, uint32_t count)
  673. {
  674. #ifdef DEBUG
  675. if (!records || !count)
  676. {
  677. write_log("missing params in %s\n", __func__);
  678. return;
  679. }
  680. for (uint32_t i = 0; i < count; i++)
  681. {
  682. ncm_print_application_record(&records[i]);
  683. }
  684. #endif
  685. }