11754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato/* 21754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato * Copyright (C) 2016 The Android Open Source Project 31754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato * 41754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato * Licensed under the Apache License, Version 2.0 (the "License"); 51754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato * you may not use this file except in compliance with the License. 61754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato * You may obtain a copy of the License at 71754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato * 81754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato * http://www.apache.org/licenses/LICENSE-2.0 91754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato * 101754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato * Unless required by applicable law or agreed to in writing, software 111754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato * distributed under the License is distributed on an "AS IS" BASIS, 121754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato * See the License for the specific language governing permissions and 141754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato * limitations under the License. 151754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato */ 164e843106a6f510a7d77fedfbeaec8e95b57905b7Yi Jin#define DEBUG false 17b592e3bc3169e39bd6b0bfce9f788631d5d22acdYi Jin#include "Log.h" 181754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 191754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include "report_directory.h" 201754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 211754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <private/android_filesystem_config.h> 221754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <utils/String8.h> 231754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 241754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <dirent.h> 251754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <libgen.h> 26b592e3bc3169e39bd6b0bfce9f788631d5d22acdYi Jin#include <sys/stat.h> 27b592e3bc3169e39bd6b0bfce9f788631d5d22acdYi Jin#include <sys/types.h> 281754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <unistd.h> 291754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 301754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <vector> 311754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 326cacbcbf436be744a34f7ea0d4f838ff97757446Yi Jinnamespace android { 336cacbcbf436be744a34f7ea0d4f838ff97757446Yi Jinnamespace os { 346cacbcbf436be744a34f7ea0d4f838ff97757446Yi Jinnamespace incidentd { 351754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 36b592e3bc3169e39bd6b0bfce9f788631d5d22acdYi Jinstatus_t create_directory(const char* directory) { 371754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato struct stat st; 381754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato status_t err = NO_ERROR; 391754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato char* dir = strdup(directory); 401754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 411754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato // Skip first slash 421754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato char* d = dir + 1; 431754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 441754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato // Create directories, assigning them to the system user 451754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato bool last = false; 461754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato while (!last) { 471754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato d = strchr(d, '/'); 481754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if (d != NULL) { 491754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato *d = '\0'; 501754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } else { 511754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato last = true; 521754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 531754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if (stat(dir, &st) == 0) { 541754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if (!S_ISDIR(st.st_mode)) { 551754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato err = ALREADY_EXISTS; 561754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato goto done; 571754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 581754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } else { 594bab3a191a70cbefac07c8fac90ec29081d91f89Yi Jin ALOGE("No such directory %s, something wrong.", dir); 604bab3a191a70cbefac07c8fac90ec29081d91f89Yi Jin err = -1; 614bab3a191a70cbefac07c8fac90ec29081d91f89Yi Jin goto done; 621754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 631754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if (!last) { 641754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato *d++ = '/'; 651754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 661754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 671754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 681754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato // Ensure that the final directory is owned by the system with 0770. If it isn't 691754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato // we won't write into it. 701754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if (stat(directory, &st) != 0) { 711754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato ALOGE("No incident reports today. Can't stat: %s", directory); 721754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato err = -errno; 731754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato goto done; 741754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 751754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if ((st.st_mode & 0777) != 0770) { 76b592e3bc3169e39bd6b0bfce9f788631d5d22acdYi Jin ALOGE("No incident reports today. Mode is %0o on report directory %s", st.st_mode, 77b592e3bc3169e39bd6b0bfce9f788631d5d22acdYi Jin directory); 781754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato err = BAD_VALUE; 791754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato goto done; 801754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 814bab3a191a70cbefac07c8fac90ec29081d91f89Yi Jin if (st.st_uid != AID_INCIDENTD || st.st_gid != AID_INCIDENTD) { 821754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato ALOGE("No incident reports today. Owner is %d and group is %d on report directory %s", 83b592e3bc3169e39bd6b0bfce9f788631d5d22acdYi Jin st.st_uid, st.st_gid, directory); 841754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato err = BAD_VALUE; 851754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato goto done; 861754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 871754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 881754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratodone: 891754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato free(dir); 901754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato return err; 911754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato} 921754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 936cacbcbf436be744a34f7ea0d4f838ff97757446Yi Jinstatic bool stat_mtime_cmp(const std::pair<String8, struct stat>& a, 946cacbcbf436be744a34f7ea0d4f838ff97757446Yi Jin const std::pair<String8, struct stat>& b) { 951754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato return a.second.st_mtime < b.second.st_mtime; 961754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato} 971754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 98b592e3bc3169e39bd6b0bfce9f788631d5d22acdYi Jinvoid clean_directory(const char* directory, off_t maxSize, size_t maxCount) { 991754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato DIR* dir; 1001754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato struct dirent* entry; 1011754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato struct stat st; 1021754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 1036cacbcbf436be744a34f7ea0d4f838ff97757446Yi Jin std::vector<std::pair<String8, struct stat>> files; 1041754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 1051754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if ((dir = opendir(directory)) == NULL) { 1061754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato ALOGE("Couldn't open incident directory: %s", directory); 1071754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato return; 1081754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 1091754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 110add11e9176f2a5a2e5193726b863d03c281a4eddYi Jin String8 dirbase(directory); 111add11e9176f2a5a2e5193726b863d03c281a4eddYi Jin if (directory[dirbase.size() - 1] != '/') dirbase += "/"; 1121754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 1131754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato off_t totalSize = 0; 1141754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato size_t totalCount = 0; 1151754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 1161754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato // Enumerate, count and add up size 1171754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato while ((entry = readdir(dir)) != NULL) { 1181754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if (entry->d_name[0] == '.') { 1191754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato continue; 1201754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 1211754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato String8 filename = dirbase + entry->d_name; 1221754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if (stat(filename.string(), &st) != 0) { 1231754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato ALOGE("Unable to stat file %s", filename.string()); 1241754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato continue; 1251754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 1261754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if (!S_ISREG(st.st_mode)) { 1271754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato continue; 1281754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 1296cacbcbf436be744a34f7ea0d4f838ff97757446Yi Jin files.push_back(std::pair<String8, struct stat>(filename, st)); 1301754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 1311754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato totalSize += st.st_size; 1321754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato totalCount++; 1331754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 1341754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 1351754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato closedir(dir); 1361754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 1371754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato // Count or size is less than max, then we're done. 1381754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if (totalSize < maxSize && totalCount < maxCount) { 1391754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato return; 1401754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 1411754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 1421754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato // Oldest files first. 1431754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato sort(files.begin(), files.end(), stat_mtime_cmp); 1441754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 1451754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato // Remove files until we're under our limits. 1466cacbcbf436be744a34f7ea0d4f838ff97757446Yi Jin for (std::vector<std::pair<String8, struct stat>>::iterator it = files.begin(); 147b592e3bc3169e39bd6b0bfce9f788631d5d22acdYi Jin it != files.end() && totalSize >= maxSize && totalCount >= maxCount; it++) { 1481754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato remove(it->first.string()); 1491754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato totalSize -= it->second.st_size; 1501754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato totalCount--; 1511754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 1521754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato} 1536cacbcbf436be744a34f7ea0d4f838ff97757446Yi Jin 1546cacbcbf436be744a34f7ea0d4f838ff97757446Yi Jin} // namespace incidentd 1556cacbcbf436be744a34f7ea0d4f838ff97757446Yi Jin} // namespace os 1566cacbcbf436be744a34f7ea0d4f838ff97757446Yi Jin} // namespace android