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