1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "bundle_backup_mgr.h"
17
18 #include "app_log_wrapper.h"
19 #include <fcntl.h>
20 #include <fstream>
21 #include "bundle_backup_service.h"
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <sys/sendfile.h>
25 #include <unistd.h>
26
27 namespace OHOS {
28 namespace AppExecFwk {
29
BundleBackupMgr()30 BundleBackupMgr::BundleBackupMgr() {}
31
~BundleBackupMgr()32 BundleBackupMgr::~BundleBackupMgr() {}
33
OnBackup(MessageParcel & data,MessageParcel & reply)34 ErrCode BundleBackupMgr::OnBackup(MessageParcel& data, MessageParcel& reply)
35 {
36 nlohmann::json backupJson = nlohmann::json::array();
37 std::shared_ptr<BundleBackupService> service = DelayedSingleton<BundleBackupService>::GetInstance();
38 if (service == nullptr) {
39 APP_LOGE("Get BundleBackupService failed");
40 return ERR_APPEXECFWK_NULL_PTR;
41 }
42 auto ret = service->OnBackup(backupJson);
43 if (ret != ERR_OK) {
44 return ret;
45 }
46 ret = SaveToFile(backupJson.dump());
47 if (ret != ERR_OK) {
48 APP_LOGE("Save backup config failed");
49 return ret;
50 }
51
52 int32_t fd = open(BACKUP_FILE_PATH, O_RDONLY);
53 if (fd < 0) {
54 APP_LOGE("Open backup file failed");
55 return ERR_APPEXECFWK_BACKUP_FILE_IO_ERROR;
56 }
57 if (!reply.WriteFileDescriptor(fd)) {
58 APP_LOGE("Write file descriptor failed");
59 close(fd);
60 return ERR_APPEXECFWK_PARCEL_ERROR;
61 }
62 return ERR_OK;
63 }
64
OnRestore(MessageParcel & data,MessageParcel & reply)65 ErrCode BundleBackupMgr::OnRestore(MessageParcel& data, MessageParcel& reply)
66 {
67 int32_t fd = data.ReadFileDescriptor();
68 if (fd < 0) {
69 return ERR_APPEXECFWK_BACKUP_INVALID_PARAMETER;
70 }
71 std::string config;
72 auto ret = LoadFromFile(fd, config);
73 (void)close(fd);
74 if (ret != ERR_OK) {
75 APP_LOGE("LoadFromFile failed");
76 return ret;
77 }
78 (void)remove(BACKUP_FILE_PATH);
79 if (config.empty() || !nlohmann::json::accept(config)) {
80 APP_LOGE("Invalid JSON format");
81 return ERR_APPEXECFWK_BACKUP_INVALID_JSON_STRUCTURE;
82 }
83 auto json = nlohmann::json::parse(config, nullptr, false);
84 if (json.is_null()) {
85 APP_LOGE("Invalid JSON structure");
86 return ERR_APPEXECFWK_BACKUP_INVALID_JSON_STRUCTURE;
87 }
88 std::shared_ptr<BundleBackupService> service = DelayedSingleton<BundleBackupService>::GetInstance();
89 if (service == nullptr) {
90 APP_LOGE("Get BundleBackupService failed");
91 return ERR_APPEXECFWK_NULL_PTR;
92 }
93 ret = service->OnRestore(json);
94 if (ret != ERR_OK) {
95 return ret;
96 }
97 return ERR_OK;
98 }
99
SaveToFile(const std::string & config)100 ErrCode BundleBackupMgr::SaveToFile(const std::string& config)
101 {
102 (void)remove(BACKUP_FILE_PATH);
103 FILE* fp = fopen(BACKUP_FILE_PATH, "w");
104 if (!fp) {
105 APP_LOGE("Save config file: %{public}s, fopen() failed", BACKUP_FILE_PATH);
106 return ERR_APPEXECFWK_BACKUP_FILE_IO_ERROR;
107 }
108 int32_t ret = static_cast<int32_t>(fwrite(config.c_str(), 1, config.length(), fp));
109 if (ret != (int32_t)config.length()) {
110 APP_LOGE("Save config file: %{public}s, fwrite %{public}d failed", BACKUP_FILE_PATH, ret);
111 (void)fclose(fp);
112 return ERR_APPEXECFWK_BACKUP_FILE_IO_ERROR;
113 }
114 (void)fflush(fp);
115 (void)fsync(fileno(fp));
116 (void)fclose(fp);
117 APP_LOGI("Save config file %{public}zu", config.size());
118 return ERR_OK;
119 }
120
LoadFromFile(int32_t fd,std::string & config)121 ErrCode BundleBackupMgr::LoadFromFile(int32_t fd, std::string& config)
122 {
123 struct stat statBuf;
124 if (fstat(fd, &statBuf) < 0) {
125 APP_LOGE("Fstat failed, errno: %{public}d", errno);
126 return ERR_APPEXECFWK_BACKUP_FILE_IO_ERROR;
127 }
128 config.resize(statBuf.st_size);
129 if (read(fd, config.data(), statBuf.st_size) != statBuf.st_size) {
130 APP_LOGE("Read file failed");
131 return ERR_APPEXECFWK_BACKUP_FILE_IO_ERROR;
132 }
133 return ERR_OK;
134 }
135 } // namespace AppExecFwk
136 } // namespace OHOS