report_directory.cpp revision 1754d744a7a34731ffc07af1bc3dbfcb06864ab0
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 */ 161754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 171754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#define LOG_TAG "incidentd" 181754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 191754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include "report_directory.h" 201754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 211754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <cutils/log.h> 221754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <private/android_filesystem_config.h> 231754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <utils/String8.h> 241754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 251754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <sys/types.h> 261754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <sys/stat.h> 271754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <dirent.h> 281754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <libgen.h> 291754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <unistd.h> 301754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 311754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato#include <vector> 321754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 331754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratousing namespace android; 341754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratousing namespace std; 351754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 361754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratostatus_t 371754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratocreate_directory(const char* directory) 381754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato{ 391754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato struct stat st; 401754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato status_t err = NO_ERROR; 411754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato char* dir = strdup(directory); 421754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 431754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato // Skip first slash 441754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato char* d = dir + 1; 451754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 461754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato // Create directories, assigning them to the system user 471754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato bool last = false; 481754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato while (!last) { 491754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato d = strchr(d, '/'); 501754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if (d != NULL) { 511754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato *d = '\0'; 521754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } else { 531754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato last = true; 541754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 551754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if (stat(dir, &st) == 0) { 561754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if (!S_ISDIR(st.st_mode)) { 571754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato err = ALREADY_EXISTS; 581754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato goto done; 591754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 601754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } else { 611754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if (mkdir(dir, 0770)) { 621754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato ALOGE("No incident reports today. " 631754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato "Unable to create incident report dir %s: %s", dir, 641754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato strerror(errno)); 651754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato err = -errno; 661754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato goto done; 671754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 681754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if (chmod(dir, 0770)) { 691754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato ALOGE("No incident reports today. " 701754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato "Unable to set permissions for incident report dir %s: %s", dir, 711754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato strerror(errno)); 721754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato err = -errno; 731754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato goto done; 741754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 751754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if (chown(dir, AID_SYSTEM, AID_SYSTEM)) { 761754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato ALOGE("No incident reports today. Unable to change ownership of dir %s: %s\n", 771754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato dir, strerror(errno)); 781754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato err = -errno; 791754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato goto done; 801754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 811754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 821754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if (!last) { 831754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato *d++ = '/'; 841754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 851754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 861754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 871754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato // Ensure that the final directory is owned by the system with 0770. If it isn't 881754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato // we won't write into it. 891754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if (stat(directory, &st) != 0) { 901754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato ALOGE("No incident reports today. Can't stat: %s", directory); 911754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato err = -errno; 921754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato goto done; 931754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 941754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if ((st.st_mode & 0777) != 0770) { 951754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato ALOGE("No incident reports today. Mode is %0o on report directory %s", 961754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato st.st_mode, directory); 971754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato err = BAD_VALUE; 981754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato goto done; 991754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 1001754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if (st.st_uid != AID_SYSTEM || st.st_gid != AID_SYSTEM) { 1011754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato ALOGE("No incident reports today. Owner is %d and group is %d on report directory %s", 1021754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato st.st_uid, st.st_gid, directory); 1031754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato err = BAD_VALUE; 1041754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato goto done; 1051754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 1061754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 1071754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratodone: 1081754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato free(dir); 1091754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato return err; 1101754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato} 1111754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 1121754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratostatic bool 1131754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratostat_mtime_cmp(const pair<String8,struct stat>& a, const pair<String8,struct stat>& b) 1141754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato{ 1151754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato return a.second.st_mtime < b.second.st_mtime; 1161754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato} 1171754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 1181754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratovoid 1191754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratoclean_directory(const char* directory, off_t maxSize, size_t maxCount) 1201754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato{ 1211754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato DIR* dir; 1221754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato struct dirent* entry; 1231754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato struct stat st; 1241754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 1251754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato vector<pair<String8,struct stat>> files; 1261754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 1271754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if ((dir = opendir(directory)) == NULL) { 1281754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato ALOGE("Couldn't open incident directory: %s", directory); 1291754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato return; 1301754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 1311754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 1321754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato String8 dirbase(String8(directory) + "/"); 1331754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 1341754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato off_t totalSize = 0; 1351754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato size_t totalCount = 0; 1361754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 1371754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato // Enumerate, count and add up size 1381754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato while ((entry = readdir(dir)) != NULL) { 1391754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if (entry->d_name[0] == '.') { 1401754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato continue; 1411754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 1421754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato String8 filename = dirbase + entry->d_name; 1431754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if (stat(filename.string(), &st) != 0) { 1441754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato ALOGE("Unable to stat file %s", filename.string()); 1451754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato continue; 1461754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 1471754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if (!S_ISREG(st.st_mode)) { 1481754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato continue; 1491754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 1501754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato files.push_back(pair<String8,struct stat>(filename, st)); 1511754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 1521754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato totalSize += st.st_size; 1531754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato totalCount++; 1541754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 1551754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 1561754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato closedir(dir); 1571754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 1581754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato // Count or size is less than max, then we're done. 1591754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if (totalSize < maxSize && totalCount < maxCount) { 1601754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato return; 1611754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 1621754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 1631754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato // Oldest files first. 1641754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato sort(files.begin(), files.end(), stat_mtime_cmp); 1651754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 1661754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato // Remove files until we're under our limits. 1671754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato for (vector<pair<String8,struct stat>>::iterator it = files.begin(); 1681754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato it != files.end() && totalSize >= maxSize && totalCount >= maxCount; it++) { 1691754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato remove(it->first.string()); 1701754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato totalSize -= it->second.st_size; 1711754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato totalCount--; 1721754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 1731754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato} 174