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