1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #define DEBUG false 17 #include "Log.h" 18 19 #include "report_directory.h" 20 21 #include <private/android_filesystem_config.h> 22 #include <utils/String8.h> 23 24 #include <dirent.h> 25 #include <libgen.h> 26 #include <sys/stat.h> 27 #include <sys/types.h> 28 #include <unistd.h> 29 30 #include <vector> 31 32 namespace android { 33 namespace os { 34 namespace incidentd { 35 36 status_t create_directory(const char* directory) { 37 struct stat st; 38 status_t err = NO_ERROR; 39 char* dir = strdup(directory); 40 41 // Skip first slash 42 char* d = dir + 1; 43 44 // Create directories, assigning them to the system user 45 bool last = false; 46 while (!last) { 47 d = strchr(d, '/'); 48 if (d != NULL) { 49 *d = '\0'; 50 } else { 51 last = true; 52 } 53 if (stat(dir, &st) == 0) { 54 if (!S_ISDIR(st.st_mode)) { 55 err = ALREADY_EXISTS; 56 goto done; 57 } 58 } else { 59 ALOGE("No such directory %s, something wrong.", dir); 60 err = -1; 61 goto done; 62 } 63 if (!last) { 64 *d++ = '/'; 65 } 66 } 67 68 // Ensure that the final directory is owned by the system with 0770. If it isn't 69 // we won't write into it. 70 if (stat(directory, &st) != 0) { 71 ALOGE("No incident reports today. Can't stat: %s", directory); 72 err = -errno; 73 goto done; 74 } 75 if ((st.st_mode & 0777) != 0770) { 76 ALOGE("No incident reports today. Mode is %0o on report directory %s", st.st_mode, 77 directory); 78 err = BAD_VALUE; 79 goto done; 80 } 81 if (st.st_uid != AID_INCIDENTD || st.st_gid != AID_INCIDENTD) { 82 ALOGE("No incident reports today. Owner is %d and group is %d on report directory %s", 83 st.st_uid, st.st_gid, directory); 84 err = BAD_VALUE; 85 goto done; 86 } 87 88 done: 89 free(dir); 90 return err; 91 } 92 93 static bool stat_mtime_cmp(const std::pair<String8, struct stat>& a, 94 const std::pair<String8, struct stat>& b) { 95 return a.second.st_mtime < b.second.st_mtime; 96 } 97 98 void clean_directory(const char* directory, off_t maxSize, size_t maxCount) { 99 DIR* dir; 100 struct dirent* entry; 101 struct stat st; 102 103 std::vector<std::pair<String8, struct stat>> files; 104 105 if ((dir = opendir(directory)) == NULL) { 106 ALOGE("Couldn't open incident directory: %s", directory); 107 return; 108 } 109 110 String8 dirbase(directory); 111 if (directory[dirbase.size() - 1] != '/') dirbase += "/"; 112 113 off_t totalSize = 0; 114 size_t totalCount = 0; 115 116 // Enumerate, count and add up size 117 while ((entry = readdir(dir)) != NULL) { 118 if (entry->d_name[0] == '.') { 119 continue; 120 } 121 String8 filename = dirbase + entry->d_name; 122 if (stat(filename.string(), &st) != 0) { 123 ALOGE("Unable to stat file %s", filename.string()); 124 continue; 125 } 126 if (!S_ISREG(st.st_mode)) { 127 continue; 128 } 129 files.push_back(std::pair<String8, struct stat>(filename, st)); 130 131 totalSize += st.st_size; 132 totalCount++; 133 } 134 135 closedir(dir); 136 137 // Count or size is less than max, then we're done. 138 if (totalSize < maxSize && totalCount < maxCount) { 139 return; 140 } 141 142 // Oldest files first. 143 sort(files.begin(), files.end(), stat_mtime_cmp); 144 145 // Remove files until we're under our limits. 146 for (std::vector<std::pair<String8, struct stat>>::iterator it = files.begin(); 147 it != files.end() && totalSize >= maxSize && totalCount >= maxCount; it++) { 148 remove(it->first.string()); 149 totalSize -= it->second.st_size; 150 totalCount--; 151 } 152 } 153 154 } // namespace incidentd 155 } // namespace os 156 } // namespace android