1 /*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "CrateManager.h"
18
19 #ifdef ENABLE_STORAGE_CRATES
20
21 #include <android-base/logging.h>
22 #include <android-base/stringprintf.h>
23 #include <android/log.h>
24 #include <errno.h>
25 #include <inttypes.h>
26 #include <libgen.h>
27 #include <stdint.h>
28 #include <string.h>
29 #include <sys/xattr.h>
30 #include <unistd.h>
31
32 #include <utils.h>
33 #include <fstream>
34 #include <functional>
35 #include <string>
36
37 #include "utils.h"
38
39 using android::base::StringPrintf;
40
41 namespace android {
42 namespace installd {
43
CrateManager(const char * uuid,userid_t userId,const std::string & packageName)44 CrateManager::CrateManager(const char* uuid, userid_t userId, const std::string& packageName) {
45 mPackageName = packageName;
46 mRoot = create_data_user_ce_package_path(uuid, userId, (const char*)packageName.c_str());
47 mCratedFoldersRoot = StringPrintf("%s/crates", mRoot.c_str());
48 }
49
~CrateManager()50 CrateManager::~CrateManager() {}
51
getValidatedCratedPath(std::string path)52 static std::string getValidatedCratedPath(std::string path) {
53 size_t pos = path.rfind("/");
54 if (pos == std::string::npos) {
55 return path;
56 }
57
58 return path.substr(pos + 1, path.length());
59 }
60
traverseChildDir(const std::string & targetDir,std::function<void (FTSENT *)> & onVisitChildDir)61 void CrateManager::traverseChildDir(const std::string& targetDir,
62 std::function<void(FTSENT*)>& onVisitChildDir) {
63 char* argv[] = {(char*)targetDir.c_str(), nullptr};
64 FTS* fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, nullptr);
65 if (fts == nullptr) {
66 PLOG(WARNING) << "Failed to fts_open " << targetDir;
67 return;
68 }
69
70 FTSENT* p;
71 while ((p = fts_read(fts)) != nullptr) {
72 switch (p->fts_info) {
73 case FTS_D:
74 if (p->fts_level == 1) {
75 onVisitChildDir(p);
76 }
77 break;
78 default:
79 break;
80 }
81
82 if (p->fts_level == 1) {
83 fts_set(fts, p, FTS_SKIP);
84 }
85 }
86 fts_close(fts);
87 }
88
traverseAllPackagesForUser(const std::optional<std::string> & uuid,userid_t userId,std::function<void (FTSENT *)> & onHandlingPackage)89 void CrateManager::traverseAllPackagesForUser(
90 const std::optional<std::string>& uuid, userid_t userId,
91 std::function<void(FTSENT*)>& onHandlingPackage) {
92 const char* uuid_ = uuid ? uuid->c_str() : nullptr;
93
94 auto ce_path = create_data_user_ce_path(uuid_, userId);
95 traverseChildDir(ce_path, onHandlingPackage);
96 }
97
createCrate(CratedFolder cratedFolder,std::function<void (CratedFolder,CrateMetadata &&)> & onCreateCrate)98 void CrateManager::createCrate(
99 CratedFolder cratedFolder,
100 std::function<void(CratedFolder, CrateMetadata&&)>& onCreateCrate) {
101 const char* path = cratedFolder->fts_path;
102 if (path == nullptr || *path == '\0') {
103 return;
104 }
105
106 CrateMetadata crateMetadata;
107 crateMetadata.uid = cratedFolder->fts_statp->st_uid;
108 crateMetadata.packageName = mPackageName;
109 crateMetadata.id = getValidatedCratedPath(path);
110
111 onCreateCrate(cratedFolder, std::move(crateMetadata));
112 }
113
traverseAllCrates(std::function<void (CratedFolder,CrateMetadata &&)> & onCreateCrate)114 void CrateManager::traverseAllCrates(std::function<void(CratedFolder, CrateMetadata&&)>& onCreateCrate) {
115 std::function<void(FTSENT*)> onVisitCrateDir = [&](FTSENT* cratedFolder) -> void {
116 createCrate(cratedFolder, onCreateCrate);
117 };
118 traverseChildDir(mCratedFoldersRoot, onVisitCrateDir);
119 }
120
121 #if CRATE_DEBUG
dump(const CrateMetadata & CrateMetadata)122 void CrateManager::dump(const CrateMetadata& CrateMetadata) {
123 LOG(DEBUG) << "CrateMetadata = {"
124 << "uid : \"" << CrateMetadata.uid
125 << "\", packageName : \"" << CrateMetadata.packageName
126 << "\", id : \"" << CrateMetadata.id
127 << "\"}";
128 }
129 #endif
130
131 } // namespace installd
132 } // namespace android
133
134 #endif // ENABLE_STORAGE_CRATES