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