blob: e1a59d4d9a2410d2ba48b6d43e6169c99ef91072 [file] [log] [blame]
Mike Lockwood94afecf2012-10-24 10:45:23 -07001/*
2** Copyright 2008, The Android Open Source Project
3**
Dave Allisond9370732014-01-30 14:19:23 -08004** 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
Mike Lockwood94afecf2012-10-24 10:45:23 -07007**
Dave Allisond9370732014-01-30 14:19:23 -08008** http://www.apache.org/licenses/LICENSE-2.0
Mike Lockwood94afecf2012-10-24 10:45:23 -07009**
Dave Allisond9370732014-01-30 14:19:23 -080010** 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
Mike Lockwood94afecf2012-10-24 10:45:23 -070014** limitations under the License.
15*/
16
Andreas Gampe02d0de52015-11-11 20:43:16 -080017#include "utils.h"
Mike Lockwood94afecf2012-10-24 10:45:23 -070018
Andreas Gampe02d0de52015-11-11 20:43:16 -080019#include <errno.h>
20#include <fcntl.h>
Jeff Sharkey3dfae0c2016-12-12 17:32:56 -070021#include <fts.h>
Andreas Gampe02d0de52015-11-11 20:43:16 -080022#include <stdlib.h>
23#include <sys/stat.h>
24#include <sys/wait.h>
Jeff Sharkey9a998f42016-07-14 18:16:22 -060025#include <sys/xattr.h>
Andreas Gampe02d0de52015-11-11 20:43:16 -080026
27#if defined(__APPLE__)
28#include <sys/mount.h>
29#else
30#include <sys/statfs.h>
31#endif
32
Mark Salyzyna5e161b2016-09-29 08:08:05 -070033#include <android/log.h>
Elliott Hughese4ec9eb2015-12-04 15:39:32 -080034#include <android-base/logging.h>
Andreas Gampe02d0de52015-11-11 20:43:16 -080035#include <android-base/stringprintf.h>
36#include <cutils/fs.h>
Andreas Gampe02d0de52015-11-11 20:43:16 -080037#include <private/android_filesystem_config.h>
Jeff Sharkeyc03de092015-04-07 18:14:05 -070038
Andreas Gampe02d0de52015-11-11 20:43:16 -080039#include "globals.h" // extern variables.
40
41#ifndef LOG_TAG
42#define LOG_TAG "installd"
43#endif
Jeff Sharkey9a998f42016-07-14 18:16:22 -060044
Mike Lockwood94afecf2012-10-24 10:45:23 -070045#define CACHE_NOISY(x) //x
Jeff Sharkey9a998f42016-07-14 18:16:22 -060046#define DEBUG_XATTRS 0
Mike Lockwood94afecf2012-10-24 10:45:23 -070047
Jeff Sharkeyc03de092015-04-07 18:14:05 -070048using android::base::StringPrintf;
Mike Lockwood94afecf2012-10-24 10:45:23 -070049
Andreas Gampe02d0de52015-11-11 20:43:16 -080050namespace android {
51namespace installd {
52
Jeff Sharkeyc03de092015-04-07 18:14:05 -070053/**
54 * Check that given string is valid filename, and that it attempts no
55 * parent or child directory traversal.
56 */
Jeff Sharkey423e7462016-12-09 18:18:43 -070057bool is_valid_filename(const std::string& name) {
Jeff Sharkeyc03de092015-04-07 18:14:05 -070058 if (name.empty() || (name == ".") || (name == "..")
59 || (name.find('/') != std::string::npos)) {
60 return false;
61 } else {
62 return true;
63 }
Mike Lockwood94afecf2012-10-24 10:45:23 -070064}
65
Calin Juravle6a1648e2016-02-01 12:12:16 +000066static void check_package_name(const char* package_name) {
67 CHECK(is_valid_filename(package_name));
Jeff Sharkey423e7462016-12-09 18:18:43 -070068 CHECK(is_valid_package_name(package_name));
Calin Juravle6a1648e2016-02-01 12:12:16 +000069}
70
Mike Lockwood94afecf2012-10-24 10:45:23 -070071/**
Jeff Sharkeyd7921182015-04-30 15:58:19 -070072 * Create the path name where package app contents should be stored for
73 * the given volume UUID and package name. An empty UUID is assumed to
74 * be internal storage.
75 */
76std::string create_data_app_package_path(const char* volume_uuid,
77 const char* package_name) {
Calin Juravle6a1648e2016-02-01 12:12:16 +000078 check_package_name(package_name);
Jeff Sharkeyd7921182015-04-30 15:58:19 -070079 return StringPrintf("%s/%s",
80 create_data_app_path(volume_uuid).c_str(), package_name);
81}
82
83/**
Jeff Sharkeyc03de092015-04-07 18:14:05 -070084 * Create the path name where package data should be stored for the given
85 * volume UUID, package name, and user ID. An empty UUID is assumed to be
86 * internal storage.
Mike Lockwood94afecf2012-10-24 10:45:23 -070087 */
Jeff Sharkey2f720f72016-04-10 20:51:40 -060088std::string create_data_user_ce_package_path(const char* volume_uuid,
Jeff Sharkeyd7921182015-04-30 15:58:19 -070089 userid_t user, const char* package_name) {
Calin Juravle6a1648e2016-02-01 12:12:16 +000090 check_package_name(package_name);
Jeff Sharkeyd7921182015-04-30 15:58:19 -070091 return StringPrintf("%s/%s",
Jeff Sharkey2f720f72016-04-10 20:51:40 -060092 create_data_user_ce_path(volume_uuid, user).c_str(), package_name);
93}
94
95std::string create_data_user_ce_package_path(const char* volume_uuid, userid_t user,
96 const char* package_name, ino_t ce_data_inode) {
97 // For testing purposes, rely on the inode when defined; this could be
98 // optimized to use access() in the future.
99 auto fallback = create_data_user_ce_package_path(volume_uuid, user, package_name);
100 if (ce_data_inode != 0) {
101 auto user_path = create_data_user_ce_path(volume_uuid, user);
102 DIR* dir = opendir(user_path.c_str());
103 if (dir == nullptr) {
104 PLOG(ERROR) << "Failed to opendir " << user_path;
105 return fallback;
106 }
107
108 struct dirent* ent;
109 while ((ent = readdir(dir))) {
110 if (ent->d_ino == ce_data_inode) {
Jeff Sharkey1d992f92016-04-13 13:45:47 -0600111 auto resolved = StringPrintf("%s/%s", user_path.c_str(), ent->d_name);
Jeff Sharkey9a998f42016-07-14 18:16:22 -0600112#if DEBUG_XATTRS
Jeff Sharkey1d992f92016-04-13 13:45:47 -0600113 if (resolved != fallback) {
114 LOG(DEBUG) << "Resolved path " << resolved << " for inode " << ce_data_inode
115 << " instead of " << fallback;
116 }
Jeff Sharkey9a998f42016-07-14 18:16:22 -0600117#endif
Jeff Sharkey2f720f72016-04-10 20:51:40 -0600118 closedir(dir);
Jeff Sharkey1d992f92016-04-13 13:45:47 -0600119 return resolved;
Jeff Sharkey2f720f72016-04-10 20:51:40 -0600120 }
121 }
Jeff Sharkey1d992f92016-04-13 13:45:47 -0600122 LOG(WARNING) << "Failed to resolve inode " << ce_data_inode << "; using " << fallback;
Jeff Sharkey2f720f72016-04-10 20:51:40 -0600123 closedir(dir);
124 return fallback;
125 } else {
126 return fallback;
127 }
Jeff Sharkeyc03de092015-04-07 18:14:05 -0700128}
Mike Lockwood94afecf2012-10-24 10:45:23 -0700129
Jeff Sharkey63ec2d62015-11-09 13:10:36 -0800130std::string create_data_user_de_package_path(const char* volume_uuid,
131 userid_t user, const char* package_name) {
Calin Juravle6a1648e2016-02-01 12:12:16 +0000132 check_package_name(package_name);
Jeff Sharkey63ec2d62015-11-09 13:10:36 -0800133 return StringPrintf("%s/%s",
134 create_data_user_de_path(volume_uuid, user).c_str(), package_name);
135}
136
Jeff Sharkeyc03de092015-04-07 18:14:05 -0700137int create_pkg_path(char path[PKG_PATH_MAX], const char *pkgname,
138 const char *postfix, userid_t userid) {
Jeff Sharkey423e7462016-12-09 18:18:43 -0700139 if (!is_valid_package_name(pkgname)) {
Jeff Sharkeyc03de092015-04-07 18:14:05 -0700140 path[0] = '\0';
Mike Lockwood94afecf2012-10-24 10:45:23 -0700141 return -1;
142 }
143
Jeff Sharkey2f720f72016-04-10 20:51:40 -0600144 std::string _tmp(create_data_user_ce_package_path(nullptr, userid, pkgname) + postfix);
Jeff Sharkeyc03de092015-04-07 18:14:05 -0700145 const char* tmp = _tmp.c_str();
146 if (strlen(tmp) >= PKG_PATH_MAX) {
147 path[0] = '\0';
148 return -1;
149 } else {
150 strcpy(path, tmp);
151 return 0;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700152 }
Mike Lockwood94afecf2012-10-24 10:45:23 -0700153}
154
Jeff Sharkey41ea4242015-04-09 11:34:03 -0700155std::string create_data_path(const char* volume_uuid) {
156 if (volume_uuid == nullptr) {
157 return "/data";
158 } else {
159 CHECK(is_valid_filename(volume_uuid));
160 return StringPrintf("/mnt/expand/%s", volume_uuid);
161 }
162}
163
Mike Lockwood94afecf2012-10-24 10:45:23 -0700164/**
Jeff Sharkeyd7921182015-04-30 15:58:19 -0700165 * Create the path name for app data.
166 */
167std::string create_data_app_path(const char* volume_uuid) {
168 return StringPrintf("%s/app", create_data_path(volume_uuid).c_str());
169}
170
171/**
Jeff Sharkeyabe4fe52013-07-10 16:55:46 -0700172 * Create the path name for user data for a certain userid.
Mike Lockwood94afecf2012-10-24 10:45:23 -0700173 */
Jeff Sharkey2f720f72016-04-10 20:51:40 -0600174std::string create_data_user_ce_path(const char* volume_uuid, userid_t userid) {
Jeff Sharkey41ea4242015-04-09 11:34:03 -0700175 std::string data(create_data_path(volume_uuid));
176 if (volume_uuid == nullptr) {
177 if (userid == 0) {
178 return StringPrintf("%s/data", data.c_str());
179 } else {
180 return StringPrintf("%s/user/%u", data.c_str(), userid);
181 }
Mike Lockwood94afecf2012-10-24 10:45:23 -0700182 } else {
Jeff Sharkey41ea4242015-04-09 11:34:03 -0700183 return StringPrintf("%s/user/%u", data.c_str(), userid);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700184 }
Mike Lockwood94afecf2012-10-24 10:45:23 -0700185}
186
187/**
Jeff Sharkey63ec2d62015-11-09 13:10:36 -0800188 * Create the path name for device encrypted user data for a certain userid.
189 */
190std::string create_data_user_de_path(const char* volume_uuid, userid_t userid) {
191 std::string data(create_data_path(volume_uuid));
192 return StringPrintf("%s/user_de/%u", data.c_str(), userid);
193}
194
195/**
Jeff Sharkeyabe4fe52013-07-10 16:55:46 -0700196 * Create the path name for media for a certain userid.
Mike Lockwood94afecf2012-10-24 10:45:23 -0700197 */
Jeff Sharkey41ea4242015-04-09 11:34:03 -0700198std::string create_data_media_path(const char* volume_uuid, userid_t userid) {
199 return StringPrintf("%s/media/%u", create_data_path(volume_uuid).c_str(), userid);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700200}
201
Jeff Sharkey3dfae0c2016-12-12 17:32:56 -0700202std::string create_data_media_package_path(const char* volume_uuid, userid_t userid,
203 const char* data_type, const char* package_name) {
204 return StringPrintf("%s/Android/%s/%s", create_data_media_path(volume_uuid, userid).c_str(),
205 data_type, package_name);
206}
207
Jeff Sharkey379a12b2016-04-14 20:45:06 -0600208std::string create_data_misc_legacy_path(userid_t userid) {
209 return StringPrintf("%s/misc/user/%u", create_data_path(nullptr).c_str(), userid);
210}
211
Calin Juravle6a1648e2016-02-01 12:12:16 +0000212std::string create_data_user_profiles_path(userid_t userid) {
213 return StringPrintf("%s/cur/%u", android_profiles_dir.path, userid);
214}
215
216std::string create_data_user_profile_package_path(userid_t user, const char* package_name) {
217 check_package_name(package_name);
218 return StringPrintf("%s/%s",create_data_user_profiles_path(user).c_str(), package_name);
219}
220
221std::string create_data_ref_profile_package_path(const char* package_name) {
222 check_package_name(package_name);
223 return StringPrintf("%s/ref/%s", android_profiles_dir.path, package_name);
224}
225
Jeff Sharkey3dfae0c2016-12-12 17:32:56 -0700226std::string create_data_dalvik_cache_path() {
227 return "/data/dalvik-cache";
228}
229
230std::string create_data_misc_foreign_dex_path(userid_t userid) {
231 return StringPrintf("/data/misc/profiles/cur/%d/foreign-dex", userid);
232}
233
Jeff Sharkey90aff262016-12-12 14:28:24 -0700234// Keep profile paths in sync with ActivityThread.
235constexpr const char* PRIMARY_PROFILE_NAME = "primary.prof";
236
237std::string create_primary_profile(const std::string& profile_dir) {
238 return StringPrintf("%s/%s", profile_dir.c_str(), PRIMARY_PROFILE_NAME);
239}
240
Jeff Sharkeye3637242015-04-08 20:56:42 -0700241std::vector<userid_t> get_known_users(const char* volume_uuid) {
242 std::vector<userid_t> users;
243
244 // We always have an owner
245 users.push_back(0);
246
247 std::string path(create_data_path(volume_uuid) + "/" + SECONDARY_USER_PREFIX);
248 DIR* dir = opendir(path.c_str());
249 if (dir == NULL) {
250 // Unable to discover other users, but at least return owner
251 PLOG(ERROR) << "Failed to opendir " << path;
252 return users;
253 }
254
255 struct dirent* ent;
256 while ((ent = readdir(dir))) {
257 if (ent->d_type != DT_DIR) {
258 continue;
259 }
260
261 char* end;
262 userid_t user = strtol(ent->d_name, &end, 10);
263 if (*end == '\0' && user != 0) {
264 LOG(DEBUG) << "Found valid user " << user;
265 users.push_back(user);
266 }
267 }
268 closedir(dir);
269
270 return users;
271}
272
Jeff Sharkey3dfae0c2016-12-12 17:32:56 -0700273int calculate_tree_size(const std::string& path, int64_t* size,
274 gid_t include_gid, gid_t exclude_gid) {
275 FTS *fts;
276 FTSENT *p;
277 char *argv[] = { (char*) path.c_str(), nullptr };
278 if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_XDEV, NULL))) {
279 if (errno != ENOENT) {
280 PLOG(ERROR) << "Failed to fts_open " << path;
281 }
282 return -1;
283 }
284 while ((p = fts_read(fts)) != NULL) {
285 switch (p->fts_info) {
286 case FTS_D:
287 case FTS_DEFAULT:
288 case FTS_F:
289 case FTS_SL:
290 case FTS_SLNONE:
291 if (include_gid != 0 && p->fts_statp->st_gid != include_gid) {
292 break;
293 }
294 if (exclude_gid != 0 && p->fts_statp->st_gid == exclude_gid) {
295 break;
296 }
297 *size += (p->fts_statp->st_blocks * 512);
298 break;
299 }
300 }
301 fts_close(fts);
302 return 0;
303}
304
Mike Lockwood94afecf2012-10-24 10:45:23 -0700305int create_move_path(char path[PKG_PATH_MAX],
306 const char* pkgname,
307 const char* leaf,
Andreas Gampe02d0de52015-11-11 20:43:16 -0800308 userid_t userid ATTRIBUTE_UNUSED)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700309{
310 if ((android_data_dir.len + strlen(PRIMARY_USER_PREFIX) + strlen(pkgname) + strlen(leaf) + 1)
311 >= PKG_PATH_MAX) {
312 return -1;
313 }
314
315 sprintf(path, "%s%s%s/%s", android_data_dir.path, PRIMARY_USER_PREFIX, pkgname, leaf);
316 return 0;
317}
318
319/**
320 * Checks whether the package name is valid. Returns -1 on error and
321 * 0 on success.
322 */
Jeff Sharkey423e7462016-12-09 18:18:43 -0700323bool is_valid_package_name(const std::string& packageName) {
324 const char* pkgname = packageName.c_str();
Mike Lockwood94afecf2012-10-24 10:45:23 -0700325 const char *x = pkgname;
326 int alpha = -1;
327
Jeff Sharkeyc03de092015-04-07 18:14:05 -0700328 if (strlen(pkgname) > PKG_NAME_MAX) {
Jeff Sharkey423e7462016-12-09 18:18:43 -0700329 return false;
Jeff Sharkeyc03de092015-04-07 18:14:05 -0700330 }
331
Mike Lockwood94afecf2012-10-24 10:45:23 -0700332 while (*x) {
333 if (isalnum(*x) || (*x == '_')) {
334 /* alphanumeric or underscore are fine */
335 } else if (*x == '.') {
336 if ((x == pkgname) || (x[1] == '.') || (x[1] == 0)) {
337 /* periods must not be first, last, or doubled */
338 ALOGE("invalid package name '%s'\n", pkgname);
Jeff Sharkey423e7462016-12-09 18:18:43 -0700339 return false;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700340 }
341 } else if (*x == '-') {
342 /* Suffix -X is fine to let versioning of packages.
343 But whatever follows should be alphanumeric.*/
344 alpha = 1;
345 } else {
346 /* anything not A-Z, a-z, 0-9, _, or . is invalid */
347 ALOGE("invalid package name '%s'\n", pkgname);
Jeff Sharkey423e7462016-12-09 18:18:43 -0700348 return false;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700349 }
350
351 x++;
352 }
353
354 if (alpha == 1) {
355 // Skip current character
356 x++;
357 while (*x) {
358 if (!isalnum(*x)) {
359 ALOGE("invalid package name '%s' should include only numbers after -\n", pkgname);
Jeff Sharkey423e7462016-12-09 18:18:43 -0700360 return false;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700361 }
362 x++;
363 }
364 }
365
Jeff Sharkey423e7462016-12-09 18:18:43 -0700366 return true;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700367}
368
Narayan Kamath3aee2c52014-06-10 13:16:47 +0100369static int _delete_dir_contents(DIR *d,
370 int (*exclusion_predicate)(const char *name, const int is_dir))
Mike Lockwood94afecf2012-10-24 10:45:23 -0700371{
372 int result = 0;
373 struct dirent *de;
374 int dfd;
375
376 dfd = dirfd(d);
377
378 if (dfd < 0) return -1;
379
380 while ((de = readdir(d))) {
381 const char *name = de->d_name;
382
Narayan Kamath3aee2c52014-06-10 13:16:47 +0100383 /* check using the exclusion predicate, if provided */
384 if (exclusion_predicate && exclusion_predicate(name, (de->d_type == DT_DIR))) {
385 continue;
386 }
Mike Lockwood94afecf2012-10-24 10:45:23 -0700387
388 if (de->d_type == DT_DIR) {
Chih-Hung Hsieh99d9fb12014-09-11 14:44:46 -0700389 int subfd;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700390 DIR *subdir;
391
392 /* always skip "." and ".." */
393 if (name[0] == '.') {
394 if (name[1] == 0) continue;
395 if ((name[1] == '.') && (name[2] == 0)) continue;
396 }
397
Nick Kralevich8b7acac2015-08-10 13:43:00 -0700398 subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700399 if (subfd < 0) {
400 ALOGE("Couldn't openat %s: %s\n", name, strerror(errno));
401 result = -1;
402 continue;
403 }
404 subdir = fdopendir(subfd);
405 if (subdir == NULL) {
406 ALOGE("Couldn't fdopendir %s: %s\n", name, strerror(errno));
407 close(subfd);
408 result = -1;
409 continue;
410 }
Narayan Kamath3aee2c52014-06-10 13:16:47 +0100411 if (_delete_dir_contents(subdir, exclusion_predicate)) {
Mike Lockwood94afecf2012-10-24 10:45:23 -0700412 result = -1;
413 }
414 closedir(subdir);
415 if (unlinkat(dfd, name, AT_REMOVEDIR) < 0) {
416 ALOGE("Couldn't unlinkat %s: %s\n", name, strerror(errno));
417 result = -1;
418 }
419 } else {
420 if (unlinkat(dfd, name, 0) < 0) {
421 ALOGE("Couldn't unlinkat %s: %s\n", name, strerror(errno));
422 result = -1;
423 }
424 }
425 }
426
427 return result;
428}
429
Calin Juravleb06f98a2016-03-28 15:11:01 +0100430int delete_dir_contents(const std::string& pathname, bool ignore_if_missing) {
431 return delete_dir_contents(pathname.c_str(), 0, NULL, ignore_if_missing);
Jeff Sharkeyebf728f2015-11-18 14:15:17 -0700432}
433
Calin Juravleb06f98a2016-03-28 15:11:01 +0100434int delete_dir_contents_and_dir(const std::string& pathname, bool ignore_if_missing) {
435 return delete_dir_contents(pathname.c_str(), 1, NULL, ignore_if_missing);
Jeff Sharkeyebf728f2015-11-18 14:15:17 -0700436}
437
Mike Lockwood94afecf2012-10-24 10:45:23 -0700438int delete_dir_contents(const char *pathname,
439 int also_delete_dir,
Calin Juravleb06f98a2016-03-28 15:11:01 +0100440 int (*exclusion_predicate)(const char*, const int),
441 bool ignore_if_missing)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700442{
443 int res = 0;
444 DIR *d;
445
446 d = opendir(pathname);
447 if (d == NULL) {
Calin Juravleb06f98a2016-03-28 15:11:01 +0100448 if (ignore_if_missing && (errno == ENOENT)) {
449 return 0;
450 }
Mike Lockwood94afecf2012-10-24 10:45:23 -0700451 ALOGE("Couldn't opendir %s: %s\n", pathname, strerror(errno));
452 return -errno;
453 }
Narayan Kamath3aee2c52014-06-10 13:16:47 +0100454 res = _delete_dir_contents(d, exclusion_predicate);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700455 closedir(d);
456 if (also_delete_dir) {
457 if (rmdir(pathname)) {
458 ALOGE("Couldn't rmdir %s: %s\n", pathname, strerror(errno));
459 res = -1;
460 }
461 }
462 return res;
463}
464
465int delete_dir_contents_fd(int dfd, const char *name)
466{
467 int fd, res;
468 DIR *d;
469
Nick Kralevich8b7acac2015-08-10 13:43:00 -0700470 fd = openat(dfd, name, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700471 if (fd < 0) {
472 ALOGE("Couldn't openat %s: %s\n", name, strerror(errno));
473 return -1;
474 }
475 d = fdopendir(fd);
476 if (d == NULL) {
477 ALOGE("Couldn't fdopendir %s: %s\n", name, strerror(errno));
478 close(fd);
479 return -1;
480 }
481 res = _delete_dir_contents(d, 0);
482 closedir(d);
483 return res;
484}
485
Robin Lee60fd3fe2014-10-07 16:55:02 +0100486static int _copy_owner_permissions(int srcfd, int dstfd)
487{
488 struct stat st;
489 if (fstat(srcfd, &st) != 0) {
490 return -1;
491 }
492 if (fchmod(dstfd, st.st_mode) != 0) {
493 return -1;
494 }
495 return 0;
496}
497
498static int _copy_dir_files(int sdfd, int ddfd, uid_t owner, gid_t group)
499{
500 int result = 0;
501 if (_copy_owner_permissions(sdfd, ddfd) != 0) {
502 ALOGE("_copy_dir_files failed to copy dir permissions\n");
503 }
504 if (fchown(ddfd, owner, group) != 0) {
505 ALOGE("_copy_dir_files failed to change dir owner\n");
506 }
507
508 DIR *ds = fdopendir(sdfd);
509 if (ds == NULL) {
510 ALOGE("Couldn't fdopendir: %s\n", strerror(errno));
511 return -1;
512 }
513 struct dirent *de;
514 while ((de = readdir(ds))) {
515 if (de->d_type != DT_REG) {
516 continue;
517 }
518
519 const char *name = de->d_name;
520 int fsfd = openat(sdfd, name, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
521 int fdfd = openat(ddfd, name, O_WRONLY | O_NOFOLLOW | O_CLOEXEC | O_CREAT, 0600);
522 if (fsfd == -1 || fdfd == -1) {
523 ALOGW("Couldn't copy %s: %s\n", name, strerror(errno));
524 } else {
525 if (_copy_owner_permissions(fsfd, fdfd) != 0) {
526 ALOGE("Failed to change file permissions\n");
527 }
528 if (fchown(fdfd, owner, group) != 0) {
529 ALOGE("Failed to change file owner\n");
530 }
531
532 char buf[8192];
533 ssize_t size;
534 while ((size = read(fsfd, buf, sizeof(buf))) > 0) {
535 write(fdfd, buf, size);
536 }
537 if (size < 0) {
538 ALOGW("Couldn't copy %s: %s\n", name, strerror(errno));
539 result = -1;
540 }
541 }
542 close(fdfd);
543 close(fsfd);
544 }
545
546 return result;
547}
548
549int copy_dir_files(const char *srcname,
550 const char *dstname,
551 uid_t owner,
552 uid_t group)
553{
554 int res = 0;
555 DIR *ds = NULL;
556 DIR *dd = NULL;
557
558 ds = opendir(srcname);
559 if (ds == NULL) {
560 ALOGE("Couldn't opendir %s: %s\n", srcname, strerror(errno));
561 return -errno;
562 }
563
564 mkdir(dstname, 0600);
565 dd = opendir(dstname);
566 if (dd == NULL) {
567 ALOGE("Couldn't opendir %s: %s\n", dstname, strerror(errno));
568 closedir(ds);
569 return -errno;
570 }
571
572 int sdfd = dirfd(ds);
573 int ddfd = dirfd(dd);
574 if (sdfd != -1 && ddfd != -1) {
575 res = _copy_dir_files(sdfd, ddfd, owner, group);
576 } else {
577 res = -errno;
578 }
579 closedir(dd);
580 closedir(ds);
581 return res;
582}
583
Jeff Sharkey41ea4242015-04-09 11:34:03 -0700584int64_t data_disk_free(const std::string& data_path)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700585{
586 struct statfs sfs;
Jeff Sharkey41ea4242015-04-09 11:34:03 -0700587 if (statfs(data_path.c_str(), &sfs) == 0) {
Mike Lockwood94afecf2012-10-24 10:45:23 -0700588 return sfs.f_bavail * sfs.f_bsize;
589 } else {
Jeff Sharkey41ea4242015-04-09 11:34:03 -0700590 PLOG(ERROR) << "Couldn't statfs " << data_path;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700591 return -1;
592 }
593}
594
595cache_t* start_cache_collection()
596{
597 cache_t* cache = (cache_t*)calloc(1, sizeof(cache_t));
598 return cache;
599}
600
601#define CACHE_BLOCK_SIZE (512*1024)
602
603static void* _cache_malloc(cache_t* cache, size_t len)
604{
605 len = (len+3)&~3;
606 if (len > (CACHE_BLOCK_SIZE/2)) {
607 // It doesn't make sense to try to put this allocation into one
608 // of our blocks, because it is so big. Instead, make a new dedicated
609 // block for it.
610 int8_t* res = (int8_t*)malloc(len+sizeof(void*));
611 if (res == NULL) {
612 return NULL;
613 }
Jeff Sharkey9a998f42016-07-14 18:16:22 -0600614 CACHE_NOISY(ALOGI("Allocated large cache mem block: %p size %zu", res, len));
Mike Lockwood94afecf2012-10-24 10:45:23 -0700615 // Link it into our list of blocks, not disrupting the current one.
616 if (cache->memBlocks == NULL) {
617 *(void**)res = NULL;
618 cache->memBlocks = res;
619 } else {
620 *(void**)res = *(void**)cache->memBlocks;
621 *(void**)cache->memBlocks = res;
622 }
623 return res + sizeof(void*);
624 }
625 int8_t* res = cache->curMemBlockAvail;
626 int8_t* nextPos = res + len;
627 if (cache->memBlocks == NULL || nextPos > cache->curMemBlockEnd) {
Jeff Sharkey19803802015-04-07 12:44:51 -0700628 int8_t* newBlock = (int8_t*) malloc(CACHE_BLOCK_SIZE);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700629 if (newBlock == NULL) {
630 return NULL;
631 }
632 CACHE_NOISY(ALOGI("Allocated new cache mem block: %p", newBlock));
633 *(void**)newBlock = cache->memBlocks;
634 cache->memBlocks = newBlock;
635 res = cache->curMemBlockAvail = newBlock + sizeof(void*);
636 cache->curMemBlockEnd = newBlock + CACHE_BLOCK_SIZE;
637 nextPos = res + len;
638 }
Jeff Sharkey9a998f42016-07-14 18:16:22 -0600639 CACHE_NOISY(ALOGI("cache_malloc: ret %p size %zu, block=%p, nextPos=%p",
Mike Lockwood94afecf2012-10-24 10:45:23 -0700640 res, len, cache->memBlocks, nextPos));
641 cache->curMemBlockAvail = nextPos;
642 return res;
643}
644
645static void* _cache_realloc(cache_t* cache, void* cur, size_t origLen, size_t len)
646{
647 // This isn't really a realloc, but it is good enough for our purposes here.
648 void* alloc = _cache_malloc(cache, len);
649 if (alloc != NULL && cur != NULL) {
650 memcpy(alloc, cur, origLen < len ? origLen : len);
651 }
652 return alloc;
653}
654
655static void _inc_num_cache_collected(cache_t* cache)
656{
657 cache->numCollected++;
658 if ((cache->numCollected%20000) == 0) {
Mark Salyzyn92dc3fc2014-03-12 13:12:44 -0700659 ALOGI("Collected cache so far: %zd directories, %zd files",
Mike Lockwood94afecf2012-10-24 10:45:23 -0700660 cache->numDirs, cache->numFiles);
661 }
662}
663
664static cache_dir_t* _add_cache_dir_t(cache_t* cache, cache_dir_t* parent, const char *name)
665{
666 size_t nameLen = strlen(name);
667 cache_dir_t* dir = (cache_dir_t*)_cache_malloc(cache, sizeof(cache_dir_t)+nameLen+1);
668 if (dir != NULL) {
669 dir->parent = parent;
670 dir->childCount = 0;
671 dir->hiddenCount = 0;
672 dir->deleted = 0;
673 strcpy(dir->name, name);
674 if (cache->numDirs >= cache->availDirs) {
675 size_t newAvail = cache->availDirs < 1000 ? 1000 : cache->availDirs*2;
676 cache_dir_t** newDirs = (cache_dir_t**)_cache_realloc(cache, cache->dirs,
677 cache->availDirs*sizeof(cache_dir_t*), newAvail*sizeof(cache_dir_t*));
678 if (newDirs == NULL) {
679 ALOGE("Failure growing cache dirs array for %s\n", name);
680 return NULL;
681 }
682 cache->availDirs = newAvail;
683 cache->dirs = newDirs;
684 }
685 cache->dirs[cache->numDirs] = dir;
686 cache->numDirs++;
687 if (parent != NULL) {
688 parent->childCount++;
689 }
690 _inc_num_cache_collected(cache);
691 } else {
692 ALOGE("Failure allocating cache_dir_t for %s\n", name);
693 }
694 return dir;
695}
696
697static cache_file_t* _add_cache_file_t(cache_t* cache, cache_dir_t* dir, time_t modTime,
698 const char *name)
699{
700 size_t nameLen = strlen(name);
701 cache_file_t* file = (cache_file_t*)_cache_malloc(cache, sizeof(cache_file_t)+nameLen+1);
702 if (file != NULL) {
703 file->dir = dir;
704 file->modTime = modTime;
705 strcpy(file->name, name);
706 if (cache->numFiles >= cache->availFiles) {
707 size_t newAvail = cache->availFiles < 1000 ? 1000 : cache->availFiles*2;
708 cache_file_t** newFiles = (cache_file_t**)_cache_realloc(cache, cache->files,
709 cache->availFiles*sizeof(cache_file_t*), newAvail*sizeof(cache_file_t*));
710 if (newFiles == NULL) {
711 ALOGE("Failure growing cache file array for %s\n", name);
712 return NULL;
713 }
714 cache->availFiles = newAvail;
715 cache->files = newFiles;
716 }
Jeff Sharkey9a998f42016-07-14 18:16:22 -0600717 CACHE_NOISY(ALOGI("Setting file %p at position %zd in array %p", file,
Mike Lockwood94afecf2012-10-24 10:45:23 -0700718 cache->numFiles, cache->files));
719 cache->files[cache->numFiles] = file;
720 cache->numFiles++;
721 dir->childCount++;
722 _inc_num_cache_collected(cache);
723 } else {
724 ALOGE("Failure allocating cache_file_t for %s\n", name);
725 }
726 return file;
727}
728
729static int _add_cache_files(cache_t *cache, cache_dir_t *parentDir, const char *dirName,
730 DIR* dir, char *pathBase, char *pathPos, size_t pathAvailLen)
731{
732 struct dirent *de;
733 cache_dir_t* cacheDir = NULL;
734 int dfd;
735
736 CACHE_NOISY(ALOGI("_add_cache_files: parent=%p dirName=%s dir=%p pathBase=%s",
737 parentDir, dirName, dir, pathBase));
738
739 dfd = dirfd(dir);
740
741 if (dfd < 0) return 0;
742
743 // Sub-directories always get added to the data structure, so if they
744 // are empty we will know about them to delete them later.
745 cacheDir = _add_cache_dir_t(cache, parentDir, dirName);
746
747 while ((de = readdir(dir))) {
748 const char *name = de->d_name;
749
750 if (de->d_type == DT_DIR) {
751 int subfd;
752 DIR *subdir;
753
754 /* always skip "." and ".." */
755 if (name[0] == '.') {
756 if (name[1] == 0) continue;
757 if ((name[1] == '.') && (name[2] == 0)) continue;
758 }
759
Nick Kralevich8b7acac2015-08-10 13:43:00 -0700760 subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700761 if (subfd < 0) {
762 ALOGE("Couldn't openat %s: %s\n", name, strerror(errno));
763 continue;
764 }
765 subdir = fdopendir(subfd);
766 if (subdir == NULL) {
767 ALOGE("Couldn't fdopendir %s: %s\n", name, strerror(errno));
768 close(subfd);
769 continue;
770 }
771 if (cacheDir == NULL) {
772 cacheDir = _add_cache_dir_t(cache, parentDir, dirName);
773 }
774 if (cacheDir != NULL) {
775 // Update pathBase for the new path... this may change dirName
776 // if that is also pointing to the path, but we are done with it
777 // now.
778 size_t finallen = snprintf(pathPos, pathAvailLen, "/%s", name);
779 CACHE_NOISY(ALOGI("Collecting dir %s\n", pathBase));
780 if (finallen < pathAvailLen) {
781 _add_cache_files(cache, cacheDir, name, subdir, pathBase,
782 pathPos+finallen, pathAvailLen-finallen);
783 } else {
784 // Whoops, the final path is too long! We'll just delete
785 // this directory.
786 ALOGW("Cache dir %s truncated in path %s; deleting dir\n",
787 name, pathBase);
788 _delete_dir_contents(subdir, NULL);
789 if (unlinkat(dfd, name, AT_REMOVEDIR) < 0) {
790 ALOGE("Couldn't unlinkat %s: %s\n", name, strerror(errno));
791 }
792 }
793 }
794 closedir(subdir);
795 } else if (de->d_type == DT_REG) {
796 // Skip files that start with '.'; they will be deleted if
797 // their entire directory is deleted. This allows for metadata
798 // like ".nomedia" to remain in the directory until the entire
799 // directory is deleted.
800 if (cacheDir == NULL) {
801 cacheDir = _add_cache_dir_t(cache, parentDir, dirName);
802 }
803 if (name[0] == '.') {
804 cacheDir->hiddenCount++;
805 continue;
806 }
807 if (cacheDir != NULL) {
808 // Build final full path for file... this may change dirName
809 // if that is also pointing to the path, but we are done with it
810 // now.
811 size_t finallen = snprintf(pathPos, pathAvailLen, "/%s", name);
812 CACHE_NOISY(ALOGI("Collecting file %s\n", pathBase));
813 if (finallen < pathAvailLen) {
814 struct stat s;
815 if (stat(pathBase, &s) >= 0) {
816 _add_cache_file_t(cache, cacheDir, s.st_mtime, name);
817 } else {
818 ALOGW("Unable to stat cache file %s; deleting\n", pathBase);
819 if (unlink(pathBase) < 0) {
820 ALOGE("Couldn't unlink %s: %s\n", pathBase, strerror(errno));
821 }
822 }
823 } else {
824 // Whoops, the final path is too long! We'll just delete
825 // this file.
826 ALOGW("Cache file %s truncated in path %s; deleting\n",
827 name, pathBase);
828 if (unlinkat(dfd, name, 0) < 0) {
829 *pathPos = 0;
830 ALOGE("Couldn't unlinkat %s in %s: %s\n", name, pathBase,
831 strerror(errno));
832 }
833 }
834 }
835 } else {
836 cacheDir->hiddenCount++;
837 }
838 }
839 return 0;
840}
841
Jeff Sharkey9a998f42016-07-14 18:16:22 -0600842int get_path_inode(const std::string& path, ino_t *inode) {
843 struct stat buf;
844 memset(&buf, 0, sizeof(buf));
845 if (stat(path.c_str(), &buf) != 0) {
846 PLOG(WARNING) << "Failed to stat " << path;
847 return -1;
848 } else {
849 *inode = buf.st_ino;
850 return 0;
851 }
852}
853
854/**
855 * Write the inode of a specific child file into the given xattr on the
856 * parent directory. This allows you to find the child later, even if its
857 * name is encrypted.
858 */
859int write_path_inode(const std::string& parent, const char* name, const char* inode_xattr) {
860 ino_t inode = 0;
861 uint64_t inode_raw = 0;
862 auto path = StringPrintf("%s/%s", parent.c_str(), name);
863
864 if (get_path_inode(path, &inode) != 0) {
865 // Path probably doesn't exist yet; ignore
866 return 0;
867 }
868
869 // Check to see if already set correctly
870 if (getxattr(parent.c_str(), inode_xattr, &inode_raw, sizeof(inode_raw)) == sizeof(inode_raw)) {
871 if (inode_raw == inode) {
872 // Already set correctly; skip writing
873 return 0;
874 } else {
875 PLOG(WARNING) << "Mismatched inode value; found " << inode
876 << " on disk but marked value was " << inode_raw << "; overwriting";
877 }
878 }
879
880 inode_raw = inode;
Jeff Sharkey4ed65072016-07-22 11:38:54 -0600881 if (setxattr(parent.c_str(), inode_xattr, &inode_raw, sizeof(inode_raw), 0) != 0 && errno != EOPNOTSUPP) {
Jeff Sharkey9a998f42016-07-14 18:16:22 -0600882 PLOG(ERROR) << "Failed to write xattr " << inode_xattr << " at " << parent;
883 return -1;
884 } else {
885 return 0;
886 }
887}
888
889/**
890 * Read the inode of a specific child file from the given xattr on the
891 * parent directory. Returns a currently valid path for that child, which
892 * might have an encrypted name.
893 */
894std::string read_path_inode(const std::string& parent, const char* name, const char* inode_xattr) {
895 ino_t inode = 0;
896 uint64_t inode_raw = 0;
897 auto fallback = StringPrintf("%s/%s", parent.c_str(), name);
898
899 // Lookup the inode value written earlier
900 if (getxattr(parent.c_str(), inode_xattr, &inode_raw, sizeof(inode_raw)) == sizeof(inode_raw)) {
901 inode = inode_raw;
902 }
903
904 // For testing purposes, rely on the inode when defined; this could be
905 // optimized to use access() in the future.
906 if (inode != 0) {
907 DIR* dir = opendir(parent.c_str());
908 if (dir == nullptr) {
909 PLOG(ERROR) << "Failed to opendir " << parent;
910 return fallback;
911 }
912
913 struct dirent* ent;
914 while ((ent = readdir(dir))) {
915 if (ent->d_ino == inode) {
916 auto resolved = StringPrintf("%s/%s", parent.c_str(), ent->d_name);
917#if DEBUG_XATTRS
918 if (resolved != fallback) {
919 LOG(DEBUG) << "Resolved path " << resolved << " for inode " << inode
920 << " instead of " << fallback;
921 }
922#endif
923 closedir(dir);
924 return resolved;
925 }
926 }
927 LOG(WARNING) << "Failed to resolve inode " << inode << "; using " << fallback;
928 closedir(dir);
929 return fallback;
930 } else {
931 return fallback;
932 }
933}
934
Jeff Sharkey54e292e2016-05-10 17:21:13 -0600935void add_cache_files(cache_t* cache, const std::string& data_path) {
Mike Lockwood94afecf2012-10-24 10:45:23 -0700936 DIR *d;
937 struct dirent *de;
938 char dirname[PATH_MAX];
939
Jeff Sharkey54e292e2016-05-10 17:21:13 -0600940 const char* basepath = data_path.c_str();
941 CACHE_NOISY(ALOGI("add_cache_files: basepath=%s\n", basepath));
Mike Lockwood94afecf2012-10-24 10:45:23 -0700942
943 d = opendir(basepath);
944 if (d == NULL) {
945 return;
946 }
947
948 while ((de = readdir(d))) {
949 if (de->d_type == DT_DIR) {
950 DIR* subdir;
951 const char *name = de->d_name;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700952
953 /* always skip "." and ".." */
954 if (name[0] == '.') {
955 if (name[1] == 0) continue;
956 if ((name[1] == '.') && (name[2] == 0)) continue;
957 }
958
Jeff Sharkey9a998f42016-07-14 18:16:22 -0600959 auto parent = StringPrintf("%s/%s", basepath, name);
960 auto resolved = read_path_inode(parent, "cache", kXattrInodeCache);
961 strcpy(dirname, resolved.c_str());
Mike Lockwood94afecf2012-10-24 10:45:23 -0700962 CACHE_NOISY(ALOGI("Adding cache files from dir: %s\n", dirname));
Jeff Sharkey54e292e2016-05-10 17:21:13 -0600963
Mike Lockwood94afecf2012-10-24 10:45:23 -0700964 subdir = opendir(dirname);
965 if (subdir != NULL) {
966 size_t dirnameLen = strlen(dirname);
967 _add_cache_files(cache, NULL, dirname, subdir, dirname, dirname+dirnameLen,
968 PATH_MAX - dirnameLen);
969 closedir(subdir);
970 }
971 }
972 }
973
974 closedir(d);
975}
976
977static char *create_dir_path(char path[PATH_MAX], cache_dir_t* dir)
978{
979 char *pos = path;
980 if (dir->parent != NULL) {
981 pos = create_dir_path(path, dir->parent);
982 }
983 // Note that we don't need to worry about going beyond the buffer,
984 // since when we were constructing the cache entries our maximum
985 // buffer size for full paths was PATH_MAX.
986 strcpy(pos, dir->name);
987 pos += strlen(pos);
988 *pos = '/';
989 pos++;
990 *pos = 0;
991 return pos;
992}
993
994static void delete_cache_dir(char path[PATH_MAX], cache_dir_t* dir)
995{
996 if (dir->parent != NULL) {
997 create_dir_path(path, dir);
998 ALOGI("DEL DIR %s\n", path);
999 if (dir->hiddenCount <= 0) {
1000 if (rmdir(path)) {
1001 ALOGE("Couldn't rmdir %s: %s\n", path, strerror(errno));
1002 return;
1003 }
1004 } else {
1005 // The directory contains hidden files so we need to delete
1006 // them along with the directory itself.
1007 if (delete_dir_contents(path, 1, NULL)) {
1008 return;
1009 }
1010 }
1011 dir->parent->childCount--;
1012 dir->deleted = 1;
1013 if (dir->parent->childCount <= 0) {
1014 delete_cache_dir(path, dir->parent);
1015 }
1016 } else if (dir->hiddenCount > 0) {
1017 // This is a root directory, but it has hidden files. Get rid of
1018 // all of those files, but not the directory itself.
1019 create_dir_path(path, dir);
1020 ALOGI("DEL CONTENTS %s\n", path);
1021 delete_dir_contents(path, 0, NULL);
1022 }
1023}
1024
1025static int cache_modtime_sort(const void *lhsP, const void *rhsP)
1026{
1027 const cache_file_t *lhs = *(const cache_file_t**)lhsP;
1028 const cache_file_t *rhs = *(const cache_file_t**)rhsP;
1029 return lhs->modTime < rhs->modTime ? -1 : (lhs->modTime > rhs->modTime ? 1 : 0);
1030}
1031
Jeff Sharkey41ea4242015-04-09 11:34:03 -07001032void clear_cache_files(const std::string& data_path, cache_t* cache, int64_t free_size)
Mike Lockwood94afecf2012-10-24 10:45:23 -07001033{
1034 size_t i;
1035 int skip = 0;
1036 char path[PATH_MAX];
1037
Mark Salyzyn92dc3fc2014-03-12 13:12:44 -07001038 ALOGI("Collected cache files: %zd directories, %zd files",
Mike Lockwood94afecf2012-10-24 10:45:23 -07001039 cache->numDirs, cache->numFiles);
1040
1041 CACHE_NOISY(ALOGI("Sorting files..."));
1042 qsort(cache->files, cache->numFiles, sizeof(cache_file_t*),
1043 cache_modtime_sort);
1044
1045 CACHE_NOISY(ALOGI("Cleaning empty directories..."));
1046 for (i=cache->numDirs; i>0; i--) {
1047 cache_dir_t* dir = cache->dirs[i-1];
1048 if (dir->childCount <= 0 && !dir->deleted) {
1049 delete_cache_dir(path, dir);
1050 }
1051 }
1052
1053 CACHE_NOISY(ALOGI("Trimming files..."));
1054 for (i=0; i<cache->numFiles; i++) {
1055 skip++;
1056 if (skip > 10) {
Jeff Sharkey41ea4242015-04-09 11:34:03 -07001057 if (data_disk_free(data_path) > free_size) {
Mike Lockwood94afecf2012-10-24 10:45:23 -07001058 return;
1059 }
1060 skip = 0;
1061 }
1062 cache_file_t* file = cache->files[i];
1063 strcpy(create_dir_path(path, file->dir), file->name);
1064 ALOGI("DEL (mod %d) %s\n", (int)file->modTime, path);
1065 if (unlink(path) < 0) {
1066 ALOGE("Couldn't unlink %s: %s\n", path, strerror(errno));
1067 }
1068 file->dir->childCount--;
1069 if (file->dir->childCount <= 0) {
1070 delete_cache_dir(path, file->dir);
1071 }
1072 }
1073}
1074
1075void finish_cache_collection(cache_t* cache)
1076{
Chih-Hung Hsieh99d9fb12014-09-11 14:44:46 -07001077 CACHE_NOISY(size_t i;)
Mike Lockwood94afecf2012-10-24 10:45:23 -07001078
Jeff Sharkey9a998f42016-07-14 18:16:22 -06001079 CACHE_NOISY(ALOGI("clear_cache_files: %zu dirs, %zu files\n", cache->numDirs, cache->numFiles));
Mike Lockwood94afecf2012-10-24 10:45:23 -07001080 CACHE_NOISY(
1081 for (i=0; i<cache->numDirs; i++) {
1082 cache_dir_t* dir = cache->dirs[i];
Jeff Sharkey9a998f42016-07-14 18:16:22 -06001083 ALOGI("dir #%zu: %p %s parent=%p\n", i, dir, dir->name, dir->parent);
Mike Lockwood94afecf2012-10-24 10:45:23 -07001084 })
1085 CACHE_NOISY(
1086 for (i=0; i<cache->numFiles; i++) {
1087 cache_file_t* file = cache->files[i];
Jeff Sharkey9a998f42016-07-14 18:16:22 -06001088 ALOGI("file #%zu: %p %s time=%d dir=%p\n", i, file, file->name,
Mike Lockwood94afecf2012-10-24 10:45:23 -07001089 (int)file->modTime, file->dir);
1090 })
1091 void* block = cache->memBlocks;
1092 while (block != NULL) {
1093 void* nextBlock = *(void**)block;
1094 CACHE_NOISY(ALOGI("Freeing cache mem block: %p", block));
1095 free(block);
1096 block = nextBlock;
1097 }
1098 free(cache);
1099}
1100
1101/**
Calin Juravlec597b6d2014-08-19 17:43:05 +01001102 * Validate that the path is valid in the context of the provided directory.
1103 * The path is allowed to have at most one subdirectory and no indirections
1104 * to top level directories (i.e. have "..").
1105 */
Jeff Sharkeye23a1322015-04-06 16:19:39 -07001106static int validate_path(const dir_rec_t* dir, const char* path, int maxSubdirs) {
Calin Juravlec597b6d2014-08-19 17:43:05 +01001107 size_t dir_len = dir->len;
1108 const char* subdir = strchr(path + dir_len, '/');
1109
1110 // Only allow the path to have at most one subdirectory.
1111 if (subdir != NULL) {
1112 ++subdir;
Jeff Sharkeye23a1322015-04-06 16:19:39 -07001113 if ((--maxSubdirs == 0) && strchr(subdir, '/') != NULL) {
Calin Juravlec597b6d2014-08-19 17:43:05 +01001114 ALOGE("invalid apk path '%s' (subdir?)\n", path);
1115 return -1;
1116 }
1117 }
1118
1119 // Directories can't have a period directly after the directory markers to prevent "..".
1120 if ((path[dir_len] == '.') || ((subdir != NULL) && (*subdir == '.'))) {
1121 ALOGE("invalid apk path '%s' (trickery)\n", path);
1122 return -1;
1123 }
1124
1125 return 0;
1126}
1127
1128/**
Mike Lockwood94afecf2012-10-24 10:45:23 -07001129 * Checks whether a path points to a system app (.apk file). Returns 0
1130 * if it is a system app or -1 if it is not.
1131 */
1132int validate_system_app_path(const char* path) {
1133 size_t i;
1134
1135 for (i = 0; i < android_system_dirs.count; i++) {
1136 const size_t dir_len = android_system_dirs.dirs[i].len;
1137 if (!strncmp(path, android_system_dirs.dirs[i].path, dir_len)) {
Jeff Sharkeye23a1322015-04-06 16:19:39 -07001138 return validate_path(android_system_dirs.dirs + i, path, 1);
Mike Lockwood94afecf2012-10-24 10:45:23 -07001139 }
1140 }
1141
1142 return -1;
1143}
1144
1145/**
1146 * Get the contents of a environment variable that contains a path. Caller
1147 * owns the string that is inserted into the directory record. Returns
1148 * 0 on success and -1 on error.
1149 */
1150int get_path_from_env(dir_rec_t* rec, const char* var) {
1151 const char* path = getenv(var);
1152 int ret = get_path_from_string(rec, path);
1153 if (ret < 0) {
1154 ALOGW("Problem finding value for environment variable %s\n", var);
1155 }
1156 return ret;
1157}
1158
1159/**
1160 * Puts the string into the record as a directory. Appends '/' to the end
1161 * of all paths. Caller owns the string that is inserted into the directory
1162 * record. A null value will result in an error.
1163 *
1164 * Returns 0 on success and -1 on error.
1165 */
1166int get_path_from_string(dir_rec_t* rec, const char* path) {
1167 if (path == NULL) {
1168 return -1;
1169 } else {
1170 const size_t path_len = strlen(path);
1171 if (path_len <= 0) {
1172 return -1;
1173 }
1174
1175 // Make sure path is absolute.
1176 if (path[0] != '/') {
1177 return -1;
1178 }
1179
1180 if (path[path_len - 1] == '/') {
1181 // Path ends with a forward slash. Make our own copy.
1182
1183 rec->path = strdup(path);
1184 if (rec->path == NULL) {
1185 return -1;
1186 }
1187
1188 rec->len = path_len;
1189 } else {
1190 // Path does not end with a slash. Generate a new string.
1191 char *dst;
1192
1193 // Add space for slash and terminating null.
1194 size_t dst_size = path_len + 2;
1195
Jeff Sharkey19803802015-04-07 12:44:51 -07001196 rec->path = (char*) malloc(dst_size);
Mike Lockwood94afecf2012-10-24 10:45:23 -07001197 if (rec->path == NULL) {
1198 return -1;
1199 }
1200
1201 dst = rec->path;
1202
1203 if (append_and_increment(&dst, path, &dst_size) < 0
1204 || append_and_increment(&dst, "/", &dst_size)) {
1205 ALOGE("Error canonicalizing path");
1206 return -1;
1207 }
1208
1209 rec->len = dst - rec->path;
1210 }
1211 }
1212 return 0;
1213}
1214
1215int copy_and_append(dir_rec_t* dst, const dir_rec_t* src, const char* suffix) {
1216 dst->len = src->len + strlen(suffix);
1217 const size_t dstSize = dst->len + 1;
1218 dst->path = (char*) malloc(dstSize);
1219
1220 if (dst->path == NULL
1221 || snprintf(dst->path, dstSize, "%s%s", src->path, suffix)
1222 != (ssize_t) dst->len) {
1223 ALOGE("Could not allocate memory to hold appended path; aborting\n");
1224 return -1;
1225 }
1226
1227 return 0;
1228}
1229
1230/**
Narayan Kamathd845c962015-06-04 13:20:27 +01001231 * Check whether path points to a valid path for an APK file. The path must
1232 * begin with a whitelisted prefix path and must be no deeper than |maxSubdirs| within
1233 * that path. Returns -1 when an invalid path is encountered and 0 when a valid path
1234 * is encountered.
Mike Lockwood94afecf2012-10-24 10:45:23 -07001235 */
Narayan Kamathd845c962015-06-04 13:20:27 +01001236static int validate_apk_path_internal(const char *path, int maxSubdirs) {
Calin Juravlec597b6d2014-08-19 17:43:05 +01001237 const dir_rec_t* dir = NULL;
Mike Lockwood94afecf2012-10-24 10:45:23 -07001238 if (!strncmp(path, android_app_dir.path, android_app_dir.len)) {
Calin Juravlec597b6d2014-08-19 17:43:05 +01001239 dir = &android_app_dir;
Mike Lockwood94afecf2012-10-24 10:45:23 -07001240 } else if (!strncmp(path, android_app_private_dir.path, android_app_private_dir.len)) {
Calin Juravlec597b6d2014-08-19 17:43:05 +01001241 dir = &android_app_private_dir;
Todd Kennedy5c1a9102015-11-23 15:18:10 -08001242 } else if (!strncmp(path, android_app_ephemeral_dir.path, android_app_ephemeral_dir.len)) {
1243 dir = &android_app_ephemeral_dir;
Mike Lockwood94afecf2012-10-24 10:45:23 -07001244 } else if (!strncmp(path, android_asec_dir.path, android_asec_dir.len)) {
Calin Juravlec597b6d2014-08-19 17:43:05 +01001245 dir = &android_asec_dir;
Jeff Sharkeye23a1322015-04-06 16:19:39 -07001246 } else if (!strncmp(path, android_mnt_expand_dir.path, android_mnt_expand_dir.len)) {
1247 dir = &android_mnt_expand_dir;
Narayan Kamathd845c962015-06-04 13:20:27 +01001248 if (maxSubdirs < 2) {
1249 maxSubdirs = 2;
1250 }
Mike Lockwood94afecf2012-10-24 10:45:23 -07001251 } else {
Mike Lockwood94afecf2012-10-24 10:45:23 -07001252 return -1;
1253 }
1254
Jeff Sharkeye23a1322015-04-06 16:19:39 -07001255 return validate_path(dir, path, maxSubdirs);
Mike Lockwood94afecf2012-10-24 10:45:23 -07001256}
1257
Narayan Kamathd845c962015-06-04 13:20:27 +01001258int validate_apk_path(const char* path) {
1259 return validate_apk_path_internal(path, 1 /* maxSubdirs */);
1260}
1261
1262int validate_apk_path_subdirs(const char* path) {
1263 return validate_apk_path_internal(path, 3 /* maxSubdirs */);
1264}
1265
Mike Lockwood94afecf2012-10-24 10:45:23 -07001266int append_and_increment(char** dst, const char* src, size_t* dst_size) {
1267 ssize_t ret = strlcpy(*dst, src, *dst_size);
1268 if (ret < 0 || (size_t) ret >= *dst_size) {
1269 return -1;
1270 }
1271 *dst += ret;
1272 *dst_size -= ret;
1273 return 0;
1274}
1275
Jeff Sharkey19803802015-04-07 12:44:51 -07001276char *build_string2(const char *s1, const char *s2) {
Mike Lockwood94afecf2012-10-24 10:45:23 -07001277 if (s1 == NULL || s2 == NULL) return NULL;
1278
1279 int len_s1 = strlen(s1);
1280 int len_s2 = strlen(s2);
1281 int len = len_s1 + len_s2 + 1;
Jeff Sharkey19803802015-04-07 12:44:51 -07001282 char *result = (char *) malloc(len);
Mike Lockwood94afecf2012-10-24 10:45:23 -07001283 if (result == NULL) return NULL;
1284
1285 strcpy(result, s1);
1286 strcpy(result + len_s1, s2);
1287
1288 return result;
1289}
1290
Jeff Sharkey19803802015-04-07 12:44:51 -07001291char *build_string3(const char *s1, const char *s2, const char *s3) {
Mike Lockwood94afecf2012-10-24 10:45:23 -07001292 if (s1 == NULL || s2 == NULL || s3 == NULL) return NULL;
1293
1294 int len_s1 = strlen(s1);
1295 int len_s2 = strlen(s2);
1296 int len_s3 = strlen(s3);
1297 int len = len_s1 + len_s2 + len_s3 + 1;
Jeff Sharkey19803802015-04-07 12:44:51 -07001298 char *result = (char *) malloc(len);
Mike Lockwood94afecf2012-10-24 10:45:23 -07001299 if (result == NULL) return NULL;
1300
1301 strcpy(result, s1);
1302 strcpy(result + len_s1, s2);
1303 strcpy(result + len_s1 + len_s2, s3);
1304
1305 return result;
1306}
1307
Robin Lee095c7632014-04-25 15:05:19 +01001308int ensure_config_user_dirs(userid_t userid) {
Robin Lee095c7632014-04-25 15:05:19 +01001309 // writable by system, readable by any app within the same user
Robin Lee60fd3fe2014-10-07 16:55:02 +01001310 const int uid = multiuser_get_uid(userid, AID_SYSTEM);
1311 const int gid = multiuser_get_uid(userid, AID_EVERYBODY);
Robin Lee095c7632014-04-25 15:05:19 +01001312
1313 // Ensure /data/misc/user/<userid> exists
Jeff Sharkey379a12b2016-04-14 20:45:06 -06001314 auto path = create_data_misc_legacy_path(userid);
1315 return fs_prepare_dir(path.c_str(), 0750, uid, gid);
Robin Lee095c7632014-04-25 15:05:19 +01001316}
Andreas Gampe02d0de52015-11-11 20:43:16 -08001317
1318int wait_child(pid_t pid)
1319{
1320 int status;
1321 pid_t got_pid;
1322
1323 while (1) {
1324 got_pid = waitpid(pid, &status, 0);
1325 if (got_pid == -1 && errno == EINTR) {
1326 printf("waitpid interrupted, retrying\n");
1327 } else {
1328 break;
1329 }
1330 }
1331 if (got_pid != pid) {
1332 ALOGW("waitpid failed: wanted %d, got %d: %s\n",
1333 (int) pid, (int) got_pid, strerror(errno));
1334 return 1;
1335 }
1336
1337 if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
1338 return 0;
1339 } else {
1340 return status; /* always nonzero */
1341 }
1342}
1343
1344} // namespace installd
1345} // namespace android