1*acea8879SAndroid Build Coastguard Worker /*
2*acea8879SAndroid Build Coastguard Worker * Copyright (C) 2010 The Android Open Source Project
3*acea8879SAndroid Build Coastguard Worker *
4*acea8879SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*acea8879SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*acea8879SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*acea8879SAndroid Build Coastguard Worker *
8*acea8879SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*acea8879SAndroid Build Coastguard Worker *
10*acea8879SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*acea8879SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*acea8879SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*acea8879SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*acea8879SAndroid Build Coastguard Worker * limitations under the License.
15*acea8879SAndroid Build Coastguard Worker */
16*acea8879SAndroid Build Coastguard Worker
17*acea8879SAndroid Build Coastguard Worker #include <dirent.h>
18*acea8879SAndroid Build Coastguard Worker #include <errno.h>
19*acea8879SAndroid Build Coastguard Worker #include <inttypes.h>
20*acea8879SAndroid Build Coastguard Worker #include <stdio.h>
21*acea8879SAndroid Build Coastguard Worker #include <stdlib.h>
22*acea8879SAndroid Build Coastguard Worker #include <string.h>
23*acea8879SAndroid Build Coastguard Worker #include <sys/stat.h>
24*acea8879SAndroid Build Coastguard Worker #include <sys/statfs.h>
25*acea8879SAndroid Build Coastguard Worker #include <unistd.h>
26*acea8879SAndroid Build Coastguard Worker
27*acea8879SAndroid Build Coastguard Worker #include <algorithm>
28*acea8879SAndroid Build Coastguard Worker #include <limits>
29*acea8879SAndroid Build Coastguard Worker #include <memory>
30*acea8879SAndroid Build Coastguard Worker #include <set>
31*acea8879SAndroid Build Coastguard Worker #include <string>
32*acea8879SAndroid Build Coastguard Worker
33*acea8879SAndroid Build Coastguard Worker #include <android-base/file.h>
34*acea8879SAndroid Build Coastguard Worker #include <android-base/logging.h>
35*acea8879SAndroid Build Coastguard Worker #include <android-base/parseint.h>
36*acea8879SAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
37*acea8879SAndroid Build Coastguard Worker #include <android-base/strings.h>
38*acea8879SAndroid Build Coastguard Worker
39*acea8879SAndroid Build Coastguard Worker #include "applypatch/applypatch.h"
40*acea8879SAndroid Build Coastguard Worker #include "otautil/paths.h"
41*acea8879SAndroid Build Coastguard Worker
EliminateOpenFiles(const std::string & dirname,std::set<std::string> * files)42*acea8879SAndroid Build Coastguard Worker static int EliminateOpenFiles(const std::string& dirname, std::set<std::string>* files) {
43*acea8879SAndroid Build Coastguard Worker std::unique_ptr<DIR, decltype(&closedir)> d(opendir("/proc"), closedir);
44*acea8879SAndroid Build Coastguard Worker if (!d) {
45*acea8879SAndroid Build Coastguard Worker PLOG(ERROR) << "Failed to open /proc";
46*acea8879SAndroid Build Coastguard Worker return -1;
47*acea8879SAndroid Build Coastguard Worker }
48*acea8879SAndroid Build Coastguard Worker struct dirent* de;
49*acea8879SAndroid Build Coastguard Worker while ((de = readdir(d.get())) != 0) {
50*acea8879SAndroid Build Coastguard Worker unsigned int pid;
51*acea8879SAndroid Build Coastguard Worker if (!android::base::ParseUint(de->d_name, &pid)) {
52*acea8879SAndroid Build Coastguard Worker continue;
53*acea8879SAndroid Build Coastguard Worker }
54*acea8879SAndroid Build Coastguard Worker std::string path = android::base::StringPrintf("/proc/%s/fd/", de->d_name);
55*acea8879SAndroid Build Coastguard Worker
56*acea8879SAndroid Build Coastguard Worker struct dirent* fdde;
57*acea8879SAndroid Build Coastguard Worker std::unique_ptr<DIR, decltype(&closedir)> fdd(opendir(path.c_str()), closedir);
58*acea8879SAndroid Build Coastguard Worker if (!fdd) {
59*acea8879SAndroid Build Coastguard Worker PLOG(ERROR) << "Failed to open " << path;
60*acea8879SAndroid Build Coastguard Worker continue;
61*acea8879SAndroid Build Coastguard Worker }
62*acea8879SAndroid Build Coastguard Worker while ((fdde = readdir(fdd.get())) != 0) {
63*acea8879SAndroid Build Coastguard Worker std::string fd_path = path + fdde->d_name;
64*acea8879SAndroid Build Coastguard Worker char link[FILENAME_MAX];
65*acea8879SAndroid Build Coastguard Worker
66*acea8879SAndroid Build Coastguard Worker int count = readlink(fd_path.c_str(), link, sizeof(link)-1);
67*acea8879SAndroid Build Coastguard Worker if (count >= 0) {
68*acea8879SAndroid Build Coastguard Worker link[count] = '\0';
69*acea8879SAndroid Build Coastguard Worker if (android::base::StartsWith(link, dirname)) {
70*acea8879SAndroid Build Coastguard Worker if (files->erase(link) > 0) {
71*acea8879SAndroid Build Coastguard Worker LOG(INFO) << link << " is open by " << de->d_name;
72*acea8879SAndroid Build Coastguard Worker }
73*acea8879SAndroid Build Coastguard Worker }
74*acea8879SAndroid Build Coastguard Worker }
75*acea8879SAndroid Build Coastguard Worker }
76*acea8879SAndroid Build Coastguard Worker }
77*acea8879SAndroid Build Coastguard Worker return 0;
78*acea8879SAndroid Build Coastguard Worker }
79*acea8879SAndroid Build Coastguard Worker
FindExpendableFiles(const std::string & dirname,const std::function<bool (const std::string &)> & name_filter)80*acea8879SAndroid Build Coastguard Worker static std::vector<std::string> FindExpendableFiles(
81*acea8879SAndroid Build Coastguard Worker const std::string& dirname, const std::function<bool(const std::string&)>& name_filter) {
82*acea8879SAndroid Build Coastguard Worker std::unique_ptr<DIR, decltype(&closedir)> d(opendir(dirname.c_str()), closedir);
83*acea8879SAndroid Build Coastguard Worker if (!d) {
84*acea8879SAndroid Build Coastguard Worker PLOG(ERROR) << "Failed to open " << dirname;
85*acea8879SAndroid Build Coastguard Worker return {};
86*acea8879SAndroid Build Coastguard Worker }
87*acea8879SAndroid Build Coastguard Worker
88*acea8879SAndroid Build Coastguard Worker // Look for regular files in the directory (not in any subdirectories).
89*acea8879SAndroid Build Coastguard Worker std::set<std::string> files;
90*acea8879SAndroid Build Coastguard Worker struct dirent* de;
91*acea8879SAndroid Build Coastguard Worker while ((de = readdir(d.get())) != 0) {
92*acea8879SAndroid Build Coastguard Worker std::string path = dirname + "/" + de->d_name;
93*acea8879SAndroid Build Coastguard Worker
94*acea8879SAndroid Build Coastguard Worker // We can't delete cache_temp_source; if it's there we might have restarted during
95*acea8879SAndroid Build Coastguard Worker // installation and could be depending on it to be there.
96*acea8879SAndroid Build Coastguard Worker if (path == Paths::Get().cache_temp_source()) {
97*acea8879SAndroid Build Coastguard Worker continue;
98*acea8879SAndroid Build Coastguard Worker }
99*acea8879SAndroid Build Coastguard Worker
100*acea8879SAndroid Build Coastguard Worker // Do not delete the file if it doesn't have the expected format.
101*acea8879SAndroid Build Coastguard Worker if (name_filter != nullptr && !name_filter(de->d_name)) {
102*acea8879SAndroid Build Coastguard Worker continue;
103*acea8879SAndroid Build Coastguard Worker }
104*acea8879SAndroid Build Coastguard Worker
105*acea8879SAndroid Build Coastguard Worker struct stat st;
106*acea8879SAndroid Build Coastguard Worker if (stat(path.c_str(), &st) == 0 && S_ISREG(st.st_mode)) {
107*acea8879SAndroid Build Coastguard Worker files.insert(path);
108*acea8879SAndroid Build Coastguard Worker }
109*acea8879SAndroid Build Coastguard Worker }
110*acea8879SAndroid Build Coastguard Worker
111*acea8879SAndroid Build Coastguard Worker LOG(INFO) << files.size() << " regular files in deletable directory";
112*acea8879SAndroid Build Coastguard Worker if (EliminateOpenFiles(dirname, &files) < 0) {
113*acea8879SAndroid Build Coastguard Worker return {};
114*acea8879SAndroid Build Coastguard Worker }
115*acea8879SAndroid Build Coastguard Worker
116*acea8879SAndroid Build Coastguard Worker return std::vector<std::string>(files.begin(), files.end());
117*acea8879SAndroid Build Coastguard Worker }
118*acea8879SAndroid Build Coastguard Worker
119*acea8879SAndroid Build Coastguard Worker // Parses the index of given log file, e.g. 3 for last_log.3; returns max number if the log name
120*acea8879SAndroid Build Coastguard Worker // doesn't have the expected format so that we'll delete these ones first.
GetLogIndex(const std::string & log_name)121*acea8879SAndroid Build Coastguard Worker static unsigned int GetLogIndex(const std::string& log_name) {
122*acea8879SAndroid Build Coastguard Worker if (log_name == "last_log" || log_name == "last_kmsg") {
123*acea8879SAndroid Build Coastguard Worker return 0;
124*acea8879SAndroid Build Coastguard Worker }
125*acea8879SAndroid Build Coastguard Worker
126*acea8879SAndroid Build Coastguard Worker unsigned int index;
127*acea8879SAndroid Build Coastguard Worker if (sscanf(log_name.c_str(), "last_log.%u", &index) == 1 ||
128*acea8879SAndroid Build Coastguard Worker sscanf(log_name.c_str(), "last_kmsg.%u", &index) == 1) {
129*acea8879SAndroid Build Coastguard Worker return index;
130*acea8879SAndroid Build Coastguard Worker }
131*acea8879SAndroid Build Coastguard Worker
132*acea8879SAndroid Build Coastguard Worker return std::numeric_limits<unsigned int>::max();
133*acea8879SAndroid Build Coastguard Worker }
134*acea8879SAndroid Build Coastguard Worker
135*acea8879SAndroid Build Coastguard Worker // Returns the amount of free space (in bytes) on the filesystem containing filename, or -1 on
136*acea8879SAndroid Build Coastguard Worker // error.
FreeSpaceForFile(const std::string & filename)137*acea8879SAndroid Build Coastguard Worker static int64_t FreeSpaceForFile(const std::string& filename) {
138*acea8879SAndroid Build Coastguard Worker struct statfs sf;
139*acea8879SAndroid Build Coastguard Worker if (statfs(filename.c_str(), &sf) == -1) {
140*acea8879SAndroid Build Coastguard Worker PLOG(ERROR) << "Failed to statfs " << filename;
141*acea8879SAndroid Build Coastguard Worker return -1;
142*acea8879SAndroid Build Coastguard Worker }
143*acea8879SAndroid Build Coastguard Worker
144*acea8879SAndroid Build Coastguard Worker auto f_bsize = static_cast<int64_t>(sf.f_bsize);
145*acea8879SAndroid Build Coastguard Worker auto free_space = sf.f_bsize * sf.f_bavail;
146*acea8879SAndroid Build Coastguard Worker if (f_bsize == 0 || free_space / f_bsize != static_cast<int64_t>(sf.f_bavail)) {
147*acea8879SAndroid Build Coastguard Worker LOG(ERROR) << "Invalid block size or overflow (sf.f_bsize " << sf.f_bsize << ", sf.f_bavail "
148*acea8879SAndroid Build Coastguard Worker << sf.f_bavail << ")";
149*acea8879SAndroid Build Coastguard Worker return -1;
150*acea8879SAndroid Build Coastguard Worker }
151*acea8879SAndroid Build Coastguard Worker return free_space;
152*acea8879SAndroid Build Coastguard Worker }
153*acea8879SAndroid Build Coastguard Worker
CheckAndFreeSpaceOnCache(size_t bytes)154*acea8879SAndroid Build Coastguard Worker bool CheckAndFreeSpaceOnCache(size_t bytes) {
155*acea8879SAndroid Build Coastguard Worker #ifndef __ANDROID__
156*acea8879SAndroid Build Coastguard Worker // TODO(xunchang): Implement a heuristic cache size check during host simulation.
157*acea8879SAndroid Build Coastguard Worker LOG(WARNING) << "Skipped making (" << bytes
158*acea8879SAndroid Build Coastguard Worker << ") bytes free space on /cache; program is running on host";
159*acea8879SAndroid Build Coastguard Worker return true;
160*acea8879SAndroid Build Coastguard Worker #endif
161*acea8879SAndroid Build Coastguard Worker
162*acea8879SAndroid Build Coastguard Worker std::vector<std::string> dirs{ "/cache", Paths::Get().cache_log_directory() };
163*acea8879SAndroid Build Coastguard Worker for (const auto& dirname : dirs) {
164*acea8879SAndroid Build Coastguard Worker if (RemoveFilesInDirectory(bytes, dirname, FreeSpaceForFile)) {
165*acea8879SAndroid Build Coastguard Worker return true;
166*acea8879SAndroid Build Coastguard Worker }
167*acea8879SAndroid Build Coastguard Worker }
168*acea8879SAndroid Build Coastguard Worker
169*acea8879SAndroid Build Coastguard Worker return false;
170*acea8879SAndroid Build Coastguard Worker }
171*acea8879SAndroid Build Coastguard Worker
RemoveFilesInDirectory(size_t bytes_needed,const std::string & dirname,const std::function<int64_t (const std::string &)> & space_checker)172*acea8879SAndroid Build Coastguard Worker bool RemoveFilesInDirectory(size_t bytes_needed, const std::string& dirname,
173*acea8879SAndroid Build Coastguard Worker const std::function<int64_t(const std::string&)>& space_checker) {
174*acea8879SAndroid Build Coastguard Worker // The requested size cannot exceed max int64_t.
175*acea8879SAndroid Build Coastguard Worker if (static_cast<uint64_t>(bytes_needed) >
176*acea8879SAndroid Build Coastguard Worker static_cast<uint64_t>(std::numeric_limits<int64_t>::max())) {
177*acea8879SAndroid Build Coastguard Worker LOG(ERROR) << "Invalid arg of bytes_needed: " << bytes_needed;
178*acea8879SAndroid Build Coastguard Worker return false;
179*acea8879SAndroid Build Coastguard Worker }
180*acea8879SAndroid Build Coastguard Worker
181*acea8879SAndroid Build Coastguard Worker struct stat st;
182*acea8879SAndroid Build Coastguard Worker if (stat(dirname.c_str(), &st) == -1) {
183*acea8879SAndroid Build Coastguard Worker PLOG(ERROR) << "Failed to stat " << dirname;
184*acea8879SAndroid Build Coastguard Worker return false;
185*acea8879SAndroid Build Coastguard Worker }
186*acea8879SAndroid Build Coastguard Worker if (!S_ISDIR(st.st_mode)) {
187*acea8879SAndroid Build Coastguard Worker LOG(ERROR) << dirname << " is not a directory";
188*acea8879SAndroid Build Coastguard Worker return false;
189*acea8879SAndroid Build Coastguard Worker }
190*acea8879SAndroid Build Coastguard Worker
191*acea8879SAndroid Build Coastguard Worker int64_t free_now = space_checker(dirname);
192*acea8879SAndroid Build Coastguard Worker if (free_now == -1) {
193*acea8879SAndroid Build Coastguard Worker LOG(ERROR) << "Failed to check free space for " << dirname;
194*acea8879SAndroid Build Coastguard Worker return false;
195*acea8879SAndroid Build Coastguard Worker }
196*acea8879SAndroid Build Coastguard Worker LOG(INFO) << free_now << " bytes free on " << dirname << " (" << bytes_needed << " needed)";
197*acea8879SAndroid Build Coastguard Worker
198*acea8879SAndroid Build Coastguard Worker if (free_now >= static_cast<int64_t>(bytes_needed)) {
199*acea8879SAndroid Build Coastguard Worker return true;
200*acea8879SAndroid Build Coastguard Worker }
201*acea8879SAndroid Build Coastguard Worker
202*acea8879SAndroid Build Coastguard Worker std::vector<std::string> files;
203*acea8879SAndroid Build Coastguard Worker if (dirname == Paths::Get().cache_log_directory()) {
204*acea8879SAndroid Build Coastguard Worker // Deletes the log files only.
205*acea8879SAndroid Build Coastguard Worker auto log_filter = [](const std::string& file_name) {
206*acea8879SAndroid Build Coastguard Worker return android::base::StartsWith(file_name, "last_log") ||
207*acea8879SAndroid Build Coastguard Worker android::base::StartsWith(file_name, "last_kmsg");
208*acea8879SAndroid Build Coastguard Worker };
209*acea8879SAndroid Build Coastguard Worker
210*acea8879SAndroid Build Coastguard Worker files = FindExpendableFiles(dirname, log_filter);
211*acea8879SAndroid Build Coastguard Worker
212*acea8879SAndroid Build Coastguard Worker // Older logs will come to the top of the queue.
213*acea8879SAndroid Build Coastguard Worker auto comparator = [](const std::string& name1, const std::string& name2) -> bool {
214*acea8879SAndroid Build Coastguard Worker unsigned int index1 = GetLogIndex(android::base::Basename(name1));
215*acea8879SAndroid Build Coastguard Worker unsigned int index2 = GetLogIndex(android::base::Basename(name2));
216*acea8879SAndroid Build Coastguard Worker if (index1 == index2) {
217*acea8879SAndroid Build Coastguard Worker return name1 < name2;
218*acea8879SAndroid Build Coastguard Worker }
219*acea8879SAndroid Build Coastguard Worker
220*acea8879SAndroid Build Coastguard Worker return index1 > index2;
221*acea8879SAndroid Build Coastguard Worker };
222*acea8879SAndroid Build Coastguard Worker
223*acea8879SAndroid Build Coastguard Worker std::sort(files.begin(), files.end(), comparator);
224*acea8879SAndroid Build Coastguard Worker } else {
225*acea8879SAndroid Build Coastguard Worker // We're allowed to delete unopened regular files in the directory.
226*acea8879SAndroid Build Coastguard Worker files = FindExpendableFiles(dirname, nullptr);
227*acea8879SAndroid Build Coastguard Worker }
228*acea8879SAndroid Build Coastguard Worker
229*acea8879SAndroid Build Coastguard Worker for (const auto& file : files) {
230*acea8879SAndroid Build Coastguard Worker if (unlink(file.c_str()) == -1) {
231*acea8879SAndroid Build Coastguard Worker PLOG(ERROR) << "Failed to delete " << file;
232*acea8879SAndroid Build Coastguard Worker continue;
233*acea8879SAndroid Build Coastguard Worker }
234*acea8879SAndroid Build Coastguard Worker
235*acea8879SAndroid Build Coastguard Worker free_now = space_checker(dirname);
236*acea8879SAndroid Build Coastguard Worker if (free_now == -1) {
237*acea8879SAndroid Build Coastguard Worker LOG(ERROR) << "Failed to check free space for " << dirname;
238*acea8879SAndroid Build Coastguard Worker return false;
239*acea8879SAndroid Build Coastguard Worker }
240*acea8879SAndroid Build Coastguard Worker LOG(INFO) << "Deleted " << file << "; now " << free_now << " bytes free";
241*acea8879SAndroid Build Coastguard Worker if (free_now >= static_cast<int64_t>(bytes_needed)) {
242*acea8879SAndroid Build Coastguard Worker return true;
243*acea8879SAndroid Build Coastguard Worker }
244*acea8879SAndroid Build Coastguard Worker }
245*acea8879SAndroid Build Coastguard Worker
246*acea8879SAndroid Build Coastguard Worker return false;
247*acea8879SAndroid Build Coastguard Worker }
248