report_directory.cpp revision b592e3bc3169e39bd6b0bfce9f788631d5d22acd
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 */ 16b592e3bc3169e39bd6b0bfce9f788631d5d22acdYi Jin#include "Log.h" 171754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 181754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include "report_directory.h" 191754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 201754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <private/android_filesystem_config.h> 211754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <utils/String8.h> 221754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 231754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <dirent.h> 241754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <libgen.h> 25b592e3bc3169e39bd6b0bfce9f788631d5d22acdYi Jin#include <sys/stat.h> 26b592e3bc3169e39bd6b0bfce9f788631d5d22acdYi Jin#include <sys/types.h> 271754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <unistd.h> 281754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 291754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <vector> 301754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 311754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratousing namespace android; 321754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratousing namespace std; 331754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 34b592e3bc3169e39bd6b0bfce9f788631d5d22acdYi Jinstatus_t create_directory(const char* directory) { 351754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato struct stat st; 361754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato status_t err = NO_ERROR; 371754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato char* dir = strdup(directory); 381754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 391754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato // Skip first slash 401754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato char* d = dir + 1; 411754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 421754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato // Create directories, assigning them to the system user 431754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato bool last = false; 441754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato while (!last) { 451754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato d = strchr(d, '/'); 461754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if (d != NULL) { 471754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato *d = '\0'; 481754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } else { 491754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato last = true; 501754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 511754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if (stat(dir, &st) == 0) { 521754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if (!S_ISDIR(st.st_mode)) { 531754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato err = ALREADY_EXISTS; 541754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato goto done; 551754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 561754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } else { 574bab3a191a70cbefac07c8fac90ec29081d91f89Yi Jin ALOGE("No such directory %s, something wrong.", dir); 584bab3a191a70cbefac07c8fac90ec29081d91f89Yi Jin err = -1; 594bab3a191a70cbefac07c8fac90ec29081d91f89Yi Jin goto done; 601754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 611754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if (!last) { 621754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato *d++ = '/'; 631754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 641754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 651754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 661754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato // Ensure that the final directory is owned by the system with 0770. If it isn't 671754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato // we won't write into it. 681754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if (stat(directory, &st) != 0) { 691754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato ALOGE("No incident reports today. Can't stat: %s", directory); 701754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato err = -errno; 711754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato goto done; 721754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 731754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if ((st.st_mode & 0777) != 0770) { 74b592e3bc3169e39bd6b0bfce9f788631d5d22acdYi Jin ALOGE("No incident reports today. Mode is %0o on report directory %s", st.st_mode, 75b592e3bc3169e39bd6b0bfce9f788631d5d22acdYi Jin directory); 761754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato err = BAD_VALUE; 771754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato goto done; 781754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 794bab3a191a70cbefac07c8fac90ec29081d91f89Yi Jin if (st.st_uid != AID_INCIDENTD || st.st_gid != AID_INCIDENTD) { 801754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato ALOGE("No incident reports today. Owner is %d and group is %d on report directory %s", 81b592e3bc3169e39bd6b0bfce9f788631d5d22acdYi Jin st.st_uid, st.st_gid, directory); 821754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato err = BAD_VALUE; 831754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato goto done; 841754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 851754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 861754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratodone: 871754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato free(dir); 881754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato return err; 891754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato} 901754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 91b592e3bc3169e39bd6b0bfce9f788631d5d22acdYi Jinstatic bool stat_mtime_cmp(const pair<String8, struct stat>& a, 92b592e3bc3169e39bd6b0bfce9f788631d5d22acdYi Jin const pair<String8, struct stat>& b) { 931754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato return a.second.st_mtime < b.second.st_mtime; 941754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato} 951754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 96b592e3bc3169e39bd6b0bfce9f788631d5d22acdYi Jinvoid clean_directory(const char* directory, off_t maxSize, size_t maxCount) { 971754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato DIR* dir; 981754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato struct dirent* entry; 991754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato struct stat st; 1001754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 101b592e3bc3169e39bd6b0bfce9f788631d5d22acdYi Jin vector<pair<String8, struct stat>> files; 1021754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 1031754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if ((dir = opendir(directory)) == NULL) { 1041754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato ALOGE("Couldn't open incident directory: %s", directory); 1051754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato return; 1061754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 1071754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 108add11e9176f2a5a2e5193726b863d03c281a4eddYi Jin String8 dirbase(directory); 109add11e9176f2a5a2e5193726b863d03c281a4eddYi Jin if (directory[dirbase.size() - 1] != '/') dirbase += "/"; 1101754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 1111754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato off_t totalSize = 0; 1121754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato size_t totalCount = 0; 1131754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 1141754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato // Enumerate, count and add up size 1151754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato while ((entry = readdir(dir)) != NULL) { 1161754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if (entry->d_name[0] == '.') { 1171754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato continue; 1181754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 1191754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato String8 filename = dirbase + entry->d_name; 1201754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if (stat(filename.string(), &st) != 0) { 1211754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato ALOGE("Unable to stat file %s", filename.string()); 1221754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato continue; 1231754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 1241754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if (!S_ISREG(st.st_mode)) { 1251754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato continue; 1261754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 127b592e3bc3169e39bd6b0bfce9f788631d5d22acdYi Jin files.push_back(pair<String8, struct stat>(filename, st)); 1281754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 1291754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato totalSize += st.st_size; 1301754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato totalCount++; 1311754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 1321754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 1331754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato closedir(dir); 1341754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 1351754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato // Count or size is less than max, then we're done. 1361754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if (totalSize < maxSize && totalCount < maxCount) { 1371754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato return; 1381754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 1391754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 1401754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato // Oldest files first. 1411754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato sort(files.begin(), files.end(), stat_mtime_cmp); 1421754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 1431754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato // Remove files until we're under our limits. 144b592e3bc3169e39bd6b0bfce9f788631d5d22acdYi Jin for (vector<pair<String8, struct stat>>::iterator it = files.begin(); 145b592e3bc3169e39bd6b0bfce9f788631d5d22acdYi Jin it != files.end() && totalSize >= maxSize && totalCount >= maxCount; it++) { 1461754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato remove(it->first.string()); 1471754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato totalSize -= it->second.st_size; 1481754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato totalCount--; 1491754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 1501754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato} 151