diff options
Diffstat (limited to 'cmds')
-rw-r--r-- | cmds/installd/commands.c | 30 | ||||
-rw-r--r-- | cmds/installd/installd.c | 150 | ||||
-rw-r--r-- | cmds/installd/installd.h | 7 | ||||
-rw-r--r-- | cmds/installd/utils.c | 50 | ||||
-rw-r--r-- | cmds/pm/src/com/android/commands/pm/Pm.java | 41 | ||||
-rw-r--r-- | cmds/svc/src/com/android/commands/svc/PowerCommand.java | 10 |
6 files changed, 251 insertions, 37 deletions
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c index d94daf7..c16e6fb 100644 --- a/cmds/installd/commands.c +++ b/cmds/installd/commands.c @@ -213,18 +213,30 @@ int make_user_data(const char *pkgname, uid_t uid, uid_t persona) int delete_persona(uid_t persona) { - char pkgdir[PKG_PATH_MAX]; + char data_path[PKG_PATH_MAX]; + if (create_persona_path(data_path, persona)) { + return -1; + } + if (delete_dir_contents(data_path, 1, NULL)) { + return -1; + } - if (create_persona_path(pkgdir, persona)) + char media_path[PATH_MAX]; + if (create_persona_media_path(media_path, (userid_t) persona) == -1) { + return -1; + } + if (delete_dir_contents(media_path, 1, NULL) == -1) { return -1; + } - return delete_dir_contents(pkgdir, 1, NULL); + return 0; } int clone_persona_data(uid_t src_persona, uid_t target_persona, int copy) { char src_data_dir[PKG_PATH_MAX]; char pkg_path[PKG_PATH_MAX]; + char media_path[PATH_MAX]; DIR *d; struct dirent *de; struct stat s; @@ -233,6 +245,9 @@ int clone_persona_data(uid_t src_persona, uid_t target_persona, int copy) if (create_persona_path(src_data_dir, src_persona)) { return -1; } + if (create_persona_media_path(media_path, (userid_t) target_persona) == -1) { + return -1; + } d = opendir(src_data_dir); if (d != NULL) { @@ -260,6 +275,11 @@ int clone_persona_data(uid_t src_persona, uid_t target_persona, int copy) } closedir(d); } + + // ensure /data/media/<user_id> exists + if (ensure_dir(media_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) { + return -1; + } return 0; } @@ -412,7 +432,7 @@ int protect(char *pkgname, gid_t gid) return 0; } -int get_size(const char *pkgname, const char *apkpath, +int get_size(const char *pkgname, int persona, const char *apkpath, const char *fwdlock_apkpath, const char *asecpath, int64_t *_codesize, int64_t *_datasize, int64_t *_cachesize, int64_t* _asecsize) @@ -459,7 +479,7 @@ int get_size(const char *pkgname, const char *apkpath, } } - if (create_pkg_path(path, pkgname, PKG_DIR_POSTFIX, 0)) { + if (create_pkg_path(path, pkgname, PKG_DIR_POSTFIX, persona)) { goto done; } diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c index 89c059e..7108d68 100644 --- a/cmds/installd/installd.c +++ b/cmds/installd/installd.c @@ -85,8 +85,9 @@ static int do_get_size(char **arg, char reply[REPLY_MAX]) int64_t asecsize = 0; int res = 0; - /* pkgdir, apkpath */ - res = get_size(arg[0], arg[1], arg[2], arg[3], &codesize, &datasize, &cachesize, &asecsize); + /* pkgdir, persona, apkpath */ + res = get_size(arg[0], atoi(arg[1]), arg[2], arg[3], arg[4], + &codesize, &datasize, &cachesize, &asecsize); /* * Each int64_t can take up 22 characters printed out. Make sure it @@ -150,7 +151,7 @@ struct cmdinfo cmds[] = { { "freecache", 1, do_free_cache }, { "rmcache", 1, do_rm_cache }, { "protect", 2, do_protect }, - { "getsize", 4, do_get_size }, + { "getsize", 5, do_get_size }, { "rmuserdata", 2, do_rm_user_data }, { "movefiles", 0, do_movefiles }, { "linklib", 2, do_linklib }, @@ -331,37 +332,138 @@ int initialize_globals() { } int initialize_directories() { + int res = -1; + int version = 0; + FILE* file; + + // Read current filesystem layout version to handle upgrade paths + char version_path[PATH_MAX]; + if (snprintf(version_path, PATH_MAX, "%s.layout_version", android_data_dir.path) > PATH_MAX) { + return -1; + } + file = fopen(version_path, "r"); + if (file != NULL) { + fscanf(file, "%d", &version); + fclose(file); + } + // /data/user char *user_data_dir = build_string2(android_data_dir.path, SECONDARY_USER_PREFIX); // /data/data char *legacy_data_dir = build_string2(android_data_dir.path, PRIMARY_USER_PREFIX); // /data/user/0 - char *primary_data_dir = build_string3(android_data_dir.path, SECONDARY_USER_PREFIX, - "0"); - int ret = -1; - if (user_data_dir != NULL && primary_data_dir != NULL && legacy_data_dir != NULL) { - ret = 0; - // Make the /data/user directory if necessary - if (access(user_data_dir, R_OK) < 0) { - if (mkdir(user_data_dir, 0711) < 0) { - return -1; - } - if (chown(user_data_dir, AID_SYSTEM, AID_SYSTEM) < 0) { - return -1; + char *primary_data_dir = build_string3(android_data_dir.path, SECONDARY_USER_PREFIX, "0"); + if (!user_data_dir || !legacy_data_dir || !primary_data_dir) { + goto fail; + } + + // Make the /data/user directory if necessary + if (access(user_data_dir, R_OK) < 0) { + if (mkdir(user_data_dir, 0711) < 0) { + goto fail; + } + if (chown(user_data_dir, AID_SYSTEM, AID_SYSTEM) < 0) { + goto fail; + } + if (chmod(user_data_dir, 0711) < 0) { + goto fail; + } + } + // Make the /data/user/0 symlink to /data/data if necessary + if (access(primary_data_dir, R_OK) < 0) { + if (symlink(legacy_data_dir, primary_data_dir)) { + goto fail; + } + } + + // /data/media/0 + char owner_media_dir[PATH_MAX]; + create_persona_media_path(owner_media_dir, 0); + + if (version == 0) { + // Introducing multi-user, so migrate /data/media contents into /data/media/0 + ALOGD("Migrating /data/media for multi-user"); + + // /data/media.tmp + char media_tmp_dir[PATH_MAX]; + snprintf(media_tmp_dir, PATH_MAX, "%smedia.tmp", android_data_dir.path); + + // Only copy when upgrade not already in progress + if (access(media_tmp_dir, F_OK) == -1) { + if (rename(android_media_dir.path, media_tmp_dir) == -1) { + ALOGE("Failed to move legacy media path: %s", strerror(errno)); + goto fail; } - if (chmod(user_data_dir, 0711) < 0) { - return -1; + } + + // Create /data/media again + if (ensure_dir(android_media_dir.path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) { + goto fail; + } + + // Move any owner data into place + if (access(media_tmp_dir, F_OK) == 0) { + if (rename(media_tmp_dir, owner_media_dir) == -1) { + ALOGE("Failed to move owner media path: %s", strerror(errno)); + goto fail; } } - // Make the /data/user/0 symlink to /data/data if necessary - if (access(primary_data_dir, R_OK) < 0) { - ret = symlink(legacy_data_dir, primary_data_dir); + + // Ensure media directories for any existing users + DIR *dir; + struct dirent *dirent; + char user_media_dir[PATH_MAX]; + + dir = opendir(user_data_dir); + if (dir != NULL) { + while ((dirent = readdir(dir))) { + if (dirent->d_type == DT_DIR) { + const char *name = dirent->d_name; + + // skip "." and ".." + if (name[0] == '.') { + if (name[1] == 0) continue; + if ((name[1] == '.') && (name[2] == 0)) continue; + } + + // /data/media/<user_id> + snprintf(user_media_dir, PATH_MAX, "%s%s", android_media_dir.path, name); + if (ensure_dir(user_media_dir, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) { + ALOGE("Failed to ensure %s: %s", user_media_dir, strerror(errno)); + goto fail; + } + } + } + closedir(dir); } - free(user_data_dir); - free(legacy_data_dir); - free(primary_data_dir); + + version = 1; } - return ret; + + // Ensure /data/media/0 is always ready + if (ensure_dir(owner_media_dir, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) { + goto fail; + } + + // Persist our current version + file = fopen(version_path, "w"); + if (file != NULL) { + fprintf(file, "%d", version); + fsync(fileno(file)); + fclose(file); + } else { + ALOGE("Failed to save version to %s: %s", version_path, strerror(errno)); + goto fail; + } + + // Success! + res = 0; + +fail: + free(user_data_dir); + free(legacy_data_dir); + free(primary_data_dir); + return res; } int main(const int argc, const char *argv[]) { diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h index f5853ff..3201427 100644 --- a/cmds/installd/installd.h +++ b/cmds/installd/installd.h @@ -35,6 +35,7 @@ #include <cutils/sockets.h> #include <cutils/log.h> #include <cutils/properties.h> +#include <cutils/multiuser.h> #include <private/android_filesystem_config.h> @@ -138,6 +139,8 @@ int create_pkg_path(char path[PKG_PATH_MAX], int create_persona_path(char path[PKG_PATH_MAX], uid_t persona); +int create_persona_media_path(char path[PKG_PATH_MAX], userid_t userid); + int create_move_path(char path[PKG_PATH_MAX], const char* pkgname, const char* leaf, @@ -180,6 +183,8 @@ int append_and_increment(char** dst, const char* src, size_t* dst_size); char *build_string2(char *s1, char *s2); char *build_string3(char *s1, char *s2, char *s3); +int ensure_dir(const char* path, mode_t mode, uid_t uid, gid_t gid); + /* commands.c */ int install(const char *pkgname, uid_t uid, gid_t gid); @@ -194,7 +199,7 @@ int delete_cache(const char *pkgname); int move_dex(const char *src, const char *dst); int rm_dex(const char *path); int protect(char *pkgname, gid_t gid); -int get_size(const char *pkgname, const char *apkpath, const char *fwdlock_apkpath, +int get_size(const char *pkgname, int persona, const char *apkpath, const char *fwdlock_apkpath, const char *asecpath, int64_t *codesize, int64_t *datasize, int64_t *cachesize, int64_t *asecsize); int free_cache(int64_t free_size); diff --git a/cmds/installd/utils.c b/cmds/installd/utils.c index 79db972..80247f1 100644 --- a/cmds/installd/utils.c +++ b/cmds/installd/utils.c @@ -137,6 +137,17 @@ int create_persona_path(char path[PKG_PATH_MAX], return 0; } +/** + * Create the path name for media for a certain persona. + * Returns 0 on success, and -1 on failure. + */ +int create_persona_media_path(char path[PATH_MAX], userid_t userid) { + if (snprintf(path, PATH_MAX, "%s%d", android_media_dir.path, userid) > PATH_MAX) { + return -1; + } + return 0; +} + int create_move_path(char path[PKG_PATH_MAX], const char* pkgname, const char* leaf, @@ -979,3 +990,42 @@ char *build_string3(char *s1, char *s2, char *s3) { return result; } + +/* Ensure that directory exists with given mode and owners. */ +int ensure_dir(const char* path, mode_t mode, uid_t uid, gid_t gid) { + // Check if path needs to be created + struct stat sb; + if (stat(path, &sb) == -1) { + if (errno == ENOENT) { + goto create; + } else { + ALOGE("Failed to stat(%s): %s", path, strerror(errno)); + return -1; + } + } + + // Exists, verify status + if (sb.st_mode == mode || sb.st_uid == uid || sb.st_gid == gid) { + return 0; + } else { + goto fixup; + } + +create: + if (mkdir(path, mode) == -1) { + ALOGE("Failed to mkdir(%s): %s", path, strerror(errno)); + return -1; + } + +fixup: + if (chown(path, uid, gid) == -1) { + ALOGE("Failed to chown(%s, %d, %d): %s", path, uid, gid, strerror(errno)); + return -1; + } + if (chmod(path, mode) == -1) { + ALOGE("Failed to chown(%s, %d): %s", path, mode, strerror(errno)); + return -1; + } + + return 0; +} diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java index eb1f9a2..b34fd05 100644 --- a/cmds/pm/src/com/android/commands/pm/Pm.java +++ b/cmds/pm/src/com/android/commands/pm/Pm.java @@ -36,6 +36,7 @@ import android.content.pm.ParceledListSlice; import android.content.pm.PermissionGroupInfo; import android.content.pm.PermissionInfo; import android.content.pm.UserInfo; +import android.content.pm.VerificationParams; import android.content.res.AssetManager; import android.content.res.Resources; import android.net.Uri; @@ -787,6 +788,8 @@ public final class Pm { String macAlgo = null; byte[] macKey = null; byte[] tag = null; + String originatingUriString = null; + String referrer = null; while ((opt=nextOption()) != null) { if (opt.equals("-l")) { @@ -850,6 +853,20 @@ public final class Pm { showUsage(); return; } + } else if (opt.equals("--originating-uri")) { + originatingUriString = nextOptionData(); + if (originatingUriString == null) { + System.err.println("Error: must supply argument for --originating-uri"); + showUsage(); + return; + } + } else if (opt.equals("--referrer")) { + referrer = nextOptionData(); + if (referrer == null) { + System.err.println("Error: must supply argument for --referrer"); + showUsage(); + return; + } } else { System.err.println("Error: Unknown option: " + opt); showUsage(); @@ -897,6 +914,20 @@ public final class Pm { final Uri apkURI; final Uri verificationURI; + final Uri originatingURI; + final Uri referrerURI; + + if (originatingUriString != null) { + originatingURI = Uri.parse(originatingUriString); + } else { + originatingURI = null; + } + + if (referrer != null) { + referrerURI = Uri.parse(referrer); + } else { + referrerURI = null; + } // Populate apkURI, must be present final String apkFilePath = nextArg(); @@ -920,8 +951,11 @@ public final class Pm { PackageInstallObserver obs = new PackageInstallObserver(); try { - mPm.installPackageWithVerification(apkURI, obs, installFlags, installerPackageName, - verificationURI, null, encryptionParams); + VerificationParams verificationParams = new VerificationParams(verificationURI, + originatingURI, referrerURI, null); + + mPm.installPackageWithVerificationAndEncryption(apkURI, obs, installFlags, + installerPackageName, verificationParams, encryptionParams); synchronized (obs) { while (!obs.finished) { @@ -1441,7 +1475,8 @@ public final class Pm { System.err.println(" pm list libraries"); System.err.println(" pm path PACKAGE"); System.err.println(" pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] [-f]"); - System.err.println(" [--algo <algorithm name> --key <key-in-hex> --iv <IV-in-hex>] PATH"); + System.err.println(" [--algo <algorithm name> --key <key-in-hex> --iv <IV-in-hex>]"); + System.err.println(" [--originating-uri <URI>] [--referrer <URI>] PATH"); System.err.println(" pm uninstall [-k] PACKAGE"); System.err.println(" pm clear PACKAGE"); System.err.println(" pm enable PACKAGE_OR_COMPONENT"); diff --git a/cmds/svc/src/com/android/commands/svc/PowerCommand.java b/cmds/svc/src/com/android/commands/svc/PowerCommand.java index deef2a3..ec3ec3e 100644 --- a/cmds/svc/src/com/android/commands/svc/PowerCommand.java +++ b/cmds/svc/src/com/android/commands/svc/PowerCommand.java @@ -37,7 +37,7 @@ public class PowerCommand extends Svc.Command { public String longHelp() { return shortHelp() + "\n" + "\n" - + "usage: svc power stayon [true|false|usb|ac]\n" + + "usage: svc power stayon [true|false|usb|ac|wireless]\n" + " Set the 'keep awake while plugged in' setting.\n"; } @@ -48,7 +48,8 @@ public class PowerCommand extends Svc.Command { int val; if ("true".equals(args[2])) { val = BatteryManager.BATTERY_PLUGGED_AC | - BatteryManager.BATTERY_PLUGGED_USB; + BatteryManager.BATTERY_PLUGGED_USB | + BatteryManager.BATTERY_PLUGGED_WIRELESS; } else if ("false".equals(args[2])) { val = 0; @@ -56,8 +57,9 @@ public class PowerCommand extends Svc.Command { val = BatteryManager.BATTERY_PLUGGED_USB; } else if ("ac".equals(args[2])) { val = BatteryManager.BATTERY_PLUGGED_AC; - } - else { + } else if ("wireless".equals(args[2])) { + val = BatteryManager.BATTERY_PLUGGED_WIRELESS; + } else { break fail; } IPowerManager pm |