/*
* Copyright (c) 2018-2019 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 .
*/
#include
#include
#include
#include "fs_save_utils.hpp"
Result FsSaveUtils::GetSaveDataSpaceIdString(const char **out_str, u8 space_id) {
const char *str = nullptr;
switch (space_id) {
case FsSaveDataSpaceId_NandSystem:
case 100: /* ProperSystem */
case 101: /* SafeMode */
str = "sys";
break;
case FsSaveDataSpaceId_NandUser:
str = "user";
break;
case FsSaveDataSpaceId_SdCard:
str = "sd_sys";
break;
case FsSaveDataSpaceId_TemporaryStorage:
str = "temp";
break;
case 4: /* SdUser */
str = "sd_user";
break;
default: /* Unexpected */
str = nullptr;
break;
}
if (str == nullptr) {
return ResultFsInvalidSaveDataSpaceId;
}
if (out_str) {
*out_str = str;
}
return ResultSuccess();
}
Result FsSaveUtils::GetSaveDataTypeString(const char **out_str, u8 save_data_type) {
const char *str = nullptr;
switch (save_data_type) {
case FsSaveDataType_SystemSaveData:
str = "system";
break;
case FsSaveDataType_SaveData:
str = "account";
break;
case FsSaveDataType_BcatDeliveryCacheStorage:
str = "bcat";
break;
case FsSaveDataType_DeviceSaveData:
str = "device";
break;
case FsSaveDataType_TemporaryStorage:
str = "temp";
break;
case FsSaveDataType_CacheStorage:
str = "cache";
break;
case 6: /* System Bcat Save */
str = "bcat_sys";
break;
default: /* Unexpected */
str = nullptr;
break;
}
if (str == nullptr) {
/* TODO: Better result? */
return ResultFsInvalidArgument;
}
if (out_str) {
*out_str = str;
}
return ResultSuccess();
}
Result FsSaveUtils::GetSaveDataDirectoryPath(FsPath &out_path, u8 space_id, u8 save_data_type, u64 title_id, u128 user_id, u64 save_id) {
const char *space_id_str, *save_type_str;
/* Get space_id, save_data_type strings. */
R_TRY(GetSaveDataSpaceIdString(&space_id_str, space_id));
R_TRY(GetSaveDataTypeString(&save_type_str, save_data_type));
/* Clear and initialize the path. */
std::memset(&out_path, 0, sizeof(out_path));
const bool is_system = (save_id != 0 && user_id == 0);
size_t out_path_len;
if (is_system) {
out_path_len = static_cast(snprintf(out_path.str, sizeof(out_path.str), "/atmosphere/saves/sysnand/%s/%s/%016lx",
space_id_str, save_type_str, save_id));
} else {
out_path_len = static_cast(snprintf(out_path.str, sizeof(out_path.str), "/atmosphere/saves/sysnand/%s/%s/%016lx/%016lx%016lx",
space_id_str, save_type_str, title_id, static_cast(user_id >> 64ul), static_cast(user_id)));
}
if (out_path_len >= sizeof(out_path)) {
/* TODO: Should we abort here? */
return ResultFsTooLongPath;
}
return ResultSuccess();
}