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