* Copyright (c) 2026 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <cstring>
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
#include <unordered_map>
#include <nlohmann/json.hpp>
#include <vector>
#include "storage_service_errno.h"
#include "storage_stats.h"
#include "bundle_stats.h"
#include "istorage_manager.h"
#include "storage_manager_proxy.h"
#include "storage_manager_connect.h"
#include "iservice_registry.h"
#include "system_ability_definition.h"
namespace OHOS {
namespace StorageManager {
constexpr int32_t ARGC_COUNT_TWO = 2;
constexpr int32_t BITS_UNIT = 1000;
constexpr int32_t SIGNIFICAND = 2;
constexpr int32_t UNITS_SIZE = 5;
static const char* TOOL_NAME = "ohos-storage-manager";
static const char* TOOL_DESC = "Storage management CLI tool for querying storage space and bundle statistics";
int OutputSuccess(const nlohmann::json& data)
{
nlohmann::json root;
root["type"] = "result";
root["status"] = "success";
root["data"] = data;
std::cout << root.dump() << std::endl;
return 0;
}
int OutputError(const std::string& code, const std::string& message, const std::string& suggestion = "")
{
nlohmann::json root;
root["type"] = "result";
root["status"] = "failed";
root["data"] = "";
root["errCode"] = code;
root["errMsg"] = message;
root["suggestion"] = suggestion;
std::cout << root.dump() << std::endl;
return 1;
}
std::string FormatBytes(int64_t bytes)
{
const char* units[] = {"B", "KB", "MB", "GB", "TB"};
int32_t i = 0;
double size = static_cast<double>(bytes);
while (size >= BITS_UNIT && i < UNITS_SIZE) {
size /= BITS_UNIT;
i++;
}
std::ostringstream ss;
ss << std::fixed << std::setprecision(SIGNIFICAND) << size << units[i];
return ss.str();
}
sptr<IStorageManager> GetStorageManagerProxy()
{
auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
if (!sam) {
return nullptr;
}
auto obj = sam->GetSystemAbility(STORAGE_MANAGER_MANAGER_ID);
return obj ? iface_cast<IStorageManager>(obj) : nullptr;
}
void PrintHelp(const std::string& subcommand = "")
{
if (subcommand.empty()) {
std::cout << TOOL_DESC << std::endl;
std::cout << "Usage: " << TOOL_NAME << " <command> [options]" << std::endl;
std::cout << " " << TOOL_NAME << " <command> --help Show help for a specific command" << std::endl;
std::cout << std::endl;
std::cout << "SubCommands:" << std::endl;
std::cout << " get-total-size Get total storage size" << std::endl;
std::cout << " get-free-size Get free storage size" << std::endl;
std::cout << " get-system-size Get system partition size" << std::endl;
std::cout << " get-user-storage-stats Get user storage statistics" << std::endl;
std::cout << " get-bundle-stats Get bundle storage statistics" << std::endl;
std::cout << " get-current-bundle-stats Get current bundle storage statistics" << std::endl;
std::cout << std::endl;
std::cout << "Options:" << std::endl;
std::cout << " --help, -h Show this help message" << std::endl;
std::cout << std::endl;
std::cout << "Examples:" << std::endl;
std::cout << " # Get total storage size" << std::endl;
std::cout << " ohos-storage-manager get-total-size" << std::endl;
std::cout << std::endl;
std::cout << " # Get free storage size" << std::endl;
std::cout << " ohos-storage-manager get-free-size" << std::endl;
std::cout << std::endl;
std::cout << " # Get user storage statistics" << std::endl;
std::cout << " ohos-storage-manager get-user-storage-stats --userId 100" << std::endl;
std::cout << std::endl;
std::cout << " # Get bundle storage statistics" << std::endl;
std::cout << " ohos-storage-manager get-user-storage-stats --packageName com.example.demo --appIndex 0"
<< std::endl;
} else {
std::cout << "SubCommands: " << subcommand << std::endl;
std::cout << "Usage: " << TOOL_NAME << " " << subcommand << " [options]" << std::endl;
std::cout << std::endl;
if (subcommand == "get-user-storage-stats") {
std::cout << "Options:" << std::endl;
std::cout << " --userId Optional integer. User ID to query. Default: current user." << std::endl;
} else if (subcommand == "get-bundle-stats") {
std::cout << "Options:" << std::endl;
std::cout << " --packageName Required string. Package name of the application." << std::endl;
std::cout << " --appIndex Optional integer. App index. Default: 0." << std::endl;
} else if (subcommand == "get-total-size" || subcommand == "get-free-size" || subcommand == "get-system-size"
|| subcommand == "get-current-bundle-stats") {
std::cout << "This subcommand has no options." << std::endl;
} else {
std::cout << "This subcommand is not supported. Please enter another one." << std::endl;
}
}
}
std::string GetOption(const std::vector<std::string>& args, const std::string& option)
{
for (size_t i = 0; i < args.size(); i++) {
if (args[i] == option && i + 1 < args.size()) {
return args[i + 1];
}
}
return "";
}
bool HasOption(const std::vector<std::string>& args, const std::string& option)
{
for (const auto& arg : args) {
if (arg == option) {
return true;
}
}
return false;
}
int CommandGetTotalSize(const std::vector<std::string>& args)
{
auto proxy = GetStorageManagerProxy();
if (!proxy) {
return OutputError("E_SERVICE_IS_NULLPTR", "Failed to get StorageManager proxy",
"Please check if the storage manager service is running");
}
int64_t size = 0;
int32_t ret = proxy->GetTotalSize(size);
if (ret != E_OK) {
return OutputError("ERR_GET_TOTAL_SIZE", "GetTotalSize failed with error code: " + std::to_string(ret),
"Please check system storage status and try again");
}
nlohmann::json data;
data["totalBytes"] = size;
data["totalReadable"] = FormatBytes(size);
return OutputSuccess(data);
}
int CommandGetFreeSize(const std::vector<std::string>& args)
{
auto proxy = GetStorageManagerProxy();
if (!proxy) {
return OutputError("E_SERVICE_IS_NULLPTR", "Failed to get StorageManager proxy",
"Please check if the storage manager service is running");
}
int64_t size = 0;
int32_t ret = proxy->GetFreeSize(size);
if (ret != E_OK) {
return OutputError("ERR_GET_FREE_SIZE", "GetFreeSize failed with error code: " + std::to_string(ret),
"Please check system storage status and try again");
}
nlohmann::json data;
data["freeBytes"] = size;
data["freeReadable"] = FormatBytes(size);
return OutputSuccess(data);
}
int CommandGetSystemSize(const std::vector<std::string>& args)
{
auto proxy = GetStorageManagerProxy();
if (!proxy) {
return OutputError("E_SERVICE_IS_NULLPTR", "Failed to get StorageManager proxy",
"Please check if the storage manager service is running");
}
int64_t size = 0;
int32_t ret = proxy->GetSystemSize(size);
if (ret != E_OK) {
return OutputError("ERR_GET_SYSTEM_SIZE", "GetSystemSize failed with error code: " + std::to_string(ret),
"Please check system storage status and try again");
}
nlohmann::json data;
data["systemBytes"] = size;
data["systemReadable"] = FormatBytes(size);
return OutputSuccess(data);
}
int CommandGetUserStorageStats(const std::vector<std::string>& args)
{
auto proxy = GetStorageManagerProxy();
if (!proxy) {
return OutputError("E_SERVICE_IS_NULLPTR", "Failed to get StorageManager proxy",
"Please check if the storage manager service is running");
}
std::string userIdStr = GetOption(args, "--userId");
int32_t userId = -1;
if (!userIdStr.empty()) {
userId = std::atoi(userIdStr.c_str());
}
StorageStats stats;
int32_t ret = (userId >= 0) ? proxy->GetUserStorageStats(userId, stats) : proxy->GetUserStorageStats(stats);
if (ret != E_OK) {
return OutputError("ERR_GET_USER_STATS", "GetUserStorageStats failed with error code: " + std::to_string(ret),
"Please check user storage statistics and try again");
}
nlohmann::json data;
data["total"] = stats.total_;
data["audio"] = stats.audio_;
data["video"] = stats.video_;
data["image"] = stats.image_;
data["file"] = stats.file_;
data["app"] = stats.app_;
data["totalReadable"] = FormatBytes(stats.total_);
return OutputSuccess(data);
}
int CommandGetBundleStats(const std::vector<std::string>& args)
{
auto proxy = GetStorageManagerProxy();
if (!proxy) {
return OutputError("E_SERVICE_IS_NULLPTR", "Failed to get StorageManager proxy",
"Please check if the storage manager service is running");
}
std::string packageName = GetOption(args, "--packageName");
if (packageName.empty()) {
return OutputError("E_PARAMS_INVALID", "Missing required parameter: --packageName",
"Please provide package name. Example: --packageName com.example.app");
}
std::string appIndexStr = GetOption(args, "--appIndex");
int32_t appIndex = appIndexStr.empty() ? 0 : std::atoi(appIndexStr.c_str());
BundleStats stats;
int32_t ret = proxy->GetBundleStats(packageName, stats, appIndex, 0);
if (ret != E_OK) {
return OutputError("ERR_GET_BUNDLE_STATS", "GetBundleStats failed with error code: " + std::to_string(ret),
"Please check bundle name and try again");
}
nlohmann::json data;
data["packageName"] = packageName;
data["appIndex"] = appIndex;
data["appSize"] = stats.appSize_;
data["cacheSize"] = stats.cacheSize_;
data["dataSize"] = stats.dataSize_;
data["appSizeReadable"] = FormatBytes(stats.appSize_);
data["cacheSizeReadable"] = FormatBytes(stats.cacheSize_);
data["dataSizeReadable"] = FormatBytes(stats.dataSize_);
return OutputSuccess(data);
}
int CommandGetCurrentBundleStats(const std::vector<std::string>& args)
{
auto proxy = GetStorageManagerProxy();
if (!proxy) {
return OutputError("E_SERVICE_IS_NULLPTR", "Failed to get StorageManager proxy",
"Please check if the storage manager service is running");
}
BundleStats stats;
int32_t ret = proxy->GetCurrentBundleStats(stats, 0);
if (ret != E_OK) {
return OutputError("ERR_GET_CURR_BUNDLE_STATS", "GetCurrentBundleStats failed with error code: " +
std::to_string(ret), "Please check current bundle storage statistics and try again");
}
nlohmann::json data;
data["appSize"] = stats.appSize_;
data["cacheSize"] = stats.cacheSize_;
data["dataSize"] = stats.dataSize_;
data["appSizeReadable"] = FormatBytes(stats.appSize_);
data["cacheSizeReadable"] = FormatBytes(stats.cacheSize_);
data["dataSizeReadable"] = FormatBytes(stats.dataSize_);
return OutputSuccess(data);
}
typedef int (*CommandHandler)(const std::vector<std::string>&);
std::unordered_map<std::string, CommandHandler> subCommands_ = {
{"get-total-size", CommandGetTotalSize},
{"get-free-size", CommandGetFreeSize},
{"get-system-size", CommandGetSystemSize},
{"get-user-storage-stats", CommandGetUserStorageStats},
{"get-bundle-stats", CommandGetBundleStats},
{"get-current-bundle-stats", CommandGetCurrentBundleStats},
};
}
}
int32_t main(int32_t argc, char* argv[])
{
using namespace OHOS::StorageManager;
if (argc < ARGC_COUNT_TWO) {
PrintHelp();
return 1;
}
std::vector<std::string> args;
for (int32_t i = ARGC_COUNT_TWO; i < argc; i++) {
args.push_back(argv[i]);
}
std::string command = argv[1];
if (command == "--help" || command == "-h") {
PrintHelp();
return 0;
}
if (HasOption(args, "--help") || HasOption(args, "-h")) {
PrintHelp(command);
return 0;
}
auto it = subCommands_.find(command);
if (it == subCommands_.end()) {
return OutputError("ERR_UNKNOWN_COMMAND", "Unknown command: " + command,
"Run 'ohos-storage-manager --help' for usage information");
}
return it->second(args);
}