Merge "Remove "unlinklib" command from installd" into jb-mr1-dev
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index 68f8400..2934261 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -27,13 +27,15 @@
 dir_rec_t android_asec_dir;
 dir_rec_t android_app_dir;
 dir_rec_t android_app_private_dir;
+dir_rec_t android_app_lib_dir;
 dir_rec_t android_media_dir;
 dir_rec_array_t android_system_dirs;
 
 int install(const char *pkgname, uid_t uid, gid_t gid)
 {
     char pkgdir[PKG_PATH_MAX];
-    char libdir[PKG_PATH_MAX];
+    char libsymlink[PKG_PATH_MAX];
+    char applibdir[PKG_PATH_MAX];
 
     if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) {
         ALOGE("invalid uid/gid: %d %d\n", uid, gid);
@@ -45,64 +47,49 @@
         return -1;
     }
 
-    if (create_pkg_path(libdir, pkgname, PKG_LIB_POSTFIX, 0)) {
-        ALOGE("cannot create package lib path\n");
+    if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, 0)) {
+        ALOGE("cannot create package lib symlink origin path\n");
+        return -1;
+    }
+
+    if (create_pkg_path_in_dir(applibdir, &android_app_lib_dir, pkgname, PKG_DIR_POSTFIX)) {
+        ALOGE("cannot create package lib symlink dest path\n");
         return -1;
     }
 
     if (mkdir(pkgdir, 0751) < 0) {
         ALOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno));
-        return -errno;
+        return -1;
     }
     if (chmod(pkgdir, 0751) < 0) {
         ALOGE("cannot chmod dir '%s': %s\n", pkgdir, strerror(errno));
         unlink(pkgdir);
-        return -errno;
+        return -1;
     }
 
-    if (mkdir(libdir, 0755) < 0) {
-        ALOGE("cannot create dir '%s': %s\n", libdir, strerror(errno));
+    if (symlink(applibdir, libsymlink) < 0) {
+        ALOGE("couldn't symlink directory '%s' -> '%s': %s\n", libsymlink, applibdir,
+                strerror(errno));
         unlink(pkgdir);
-        return -errno;
-    }
-    if (chmod(libdir, 0755) < 0) {
-        ALOGE("cannot chmod dir '%s': %s\n", libdir, strerror(errno));
-        unlink(libdir);
-        unlink(pkgdir);
-        return -errno;
-    }
-    if (chown(libdir, AID_SYSTEM, AID_SYSTEM) < 0) {
-        ALOGE("cannot chown dir '%s': %s\n", libdir, strerror(errno));
-        unlink(libdir);
-        unlink(pkgdir);
-        return -errno;
-    }
-
-#ifdef HAVE_SELINUX
-    if (selinux_android_setfilecon(libdir, pkgname, AID_SYSTEM) < 0) {
-        ALOGE("cannot setfilecon dir '%s': %s\n", libdir, strerror(errno));
-        unlink(libdir);
-        unlink(pkgdir);
-        return -errno;
-    }
-#endif
-
-    if (chown(pkgdir, uid, gid) < 0) {
-        ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno));
-        unlink(libdir);
-        unlink(pkgdir);
-        return -errno;
+        return -1;
     }
 
 #ifdef HAVE_SELINUX
     if (selinux_android_setfilecon(pkgdir, pkgname, uid) < 0) {
         ALOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno));
-        unlink(libdir);
+        unlink(libsymlink);
         unlink(pkgdir);
-        return -errno;
+        return -1;
     }
 #endif
 
+    if (chown(pkgdir, uid, gid) < 0) {
+        ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno));
+        unlink(libsymlink);
+        unlink(pkgdir);
+        return -1;
+    }
+
     return 0;
 }
 
@@ -185,7 +172,6 @@
 int make_user_data(const char *pkgname, uid_t uid, uid_t persona)
 {
     char pkgdir[PKG_PATH_MAX];
-    char real_libdir[PKG_PATH_MAX];
 
     // Create the data dir for the package
     if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, persona)) {
@@ -1038,85 +1024,3 @@
 
     return rc;
 }
-
-int unlinklib(const char* dataDir)
-{
-    char libdir[PKG_PATH_MAX];
-    struct stat s, libStat;
-    int rc = 0;
-
-    const size_t libdirLen = strlen(dataDir) + strlen(PKG_LIB_POSTFIX);
-    if (libdirLen >= PKG_PATH_MAX) {
-        return -1;
-    }
-
-    if (snprintf(libdir, sizeof(libdir), "%s%s", dataDir, PKG_LIB_POSTFIX) != (ssize_t)libdirLen) {
-        ALOGE("library dir not written successfully: %s\n", strerror(errno));
-        return -1;
-    }
-
-    if (stat(dataDir, &s) < 0) {
-        ALOGE("couldn't state data dir");
-        return -1;
-    }
-
-    if (chown(dataDir, AID_INSTALL, AID_INSTALL) < 0) {
-        ALOGE("failed to chown '%s': %s\n", dataDir, strerror(errno));
-        return -1;
-    }
-
-    if (chmod(dataDir, 0700) < 0) {
-        ALOGE("unlinklib() 1: failed to chmod '%s': %s\n", dataDir, strerror(errno));
-        rc = -1;
-        goto out;
-    }
-
-    if (lstat(libdir, &libStat) < 0) {
-        ALOGE("couldn't stat lib dir: %s\n", strerror(errno));
-        rc = -1;
-        goto out;
-    }
-
-    if (S_ISDIR(libStat.st_mode)) {
-        if (delete_dir_contents(libdir, 1, 0) < 0) {
-            rc = -1;
-            goto out;
-        }
-    } else if (S_ISLNK(libStat.st_mode)) {
-        if (unlink(libdir) < 0) {
-            rc = -1;
-            goto out;
-        }
-    }
-
-    if (mkdir(libdir, 0755) < 0) {
-        ALOGE("cannot create dir '%s': %s\n", libdir, strerror(errno));
-        rc = -errno;
-        goto out;
-    }
-    if (chmod(libdir, 0755) < 0) {
-        ALOGE("cannot chmod dir '%s': %s\n", libdir, strerror(errno));
-        unlink(libdir);
-        rc = -errno;
-        goto out;
-    }
-    if (chown(libdir, AID_SYSTEM, AID_SYSTEM) < 0) {
-        ALOGE("cannot chown dir '%s': %s\n", libdir, strerror(errno));
-        unlink(libdir);
-        rc = -errno;
-        goto out;
-    }
-
-out:
-    if (chmod(dataDir, s.st_mode) < 0) {
-        ALOGE("unlinklib() 2: failed to chmod '%s': %s\n", dataDir, strerror(errno));
-        rc = -1;
-    }
-
-    if (chown(dataDir, s.st_uid, s.st_gid) < 0) {
-        ALOGE("failed to chown '%s' : %s\n", dataDir, strerror(errno));
-        return -1;
-    }
-
-    return rc;
-}
diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c
index cc8f014..a099537 100644
--- a/cmds/installd/installd.c
+++ b/cmds/installd/installd.c
@@ -126,11 +126,6 @@
     return linklib(arg[0], arg[1]);
 }
 
-static int do_unlinklib(char **arg, char reply[REPLY_MAX])
-{
-    return unlinklib(arg[0]);
-}
-
 struct cmdinfo {
     const char *name;
     unsigned numargs;
@@ -152,7 +147,6 @@
     { "rmuserdata",           2, do_rm_user_data },
     { "movefiles",            0, do_movefiles },
     { "linklib",              2, do_linklib },
-    { "unlinklib",            1, do_unlinklib },
     { "mkuserdata",           3, do_mk_user_data },
     { "rmuser",               1, do_rm_user },
     { "cloneuserdata",        3, do_clone_user_data },
@@ -290,6 +284,11 @@
         return -1;
     }
 
+    // Get the android app native library directory.
+    if (copy_and_append(&android_app_lib_dir, &android_data_dir, APP_LIB_SUBDIR) < 0) {
+        return -1;
+    }
+
     // Get the sd-card ASEC mount point.
     if (get_path_from_env(&android_asec_dir, "ASEC_MOUNTPOINT") < 0) {
         return -1;
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
index 5b81d2c..a229b970 100644
--- a/cmds/installd/installd.h
+++ b/cmds/installd/installd.h
@@ -62,6 +62,8 @@
 
 #define APP_SUBDIR             "app/" // sub-directory under ANDROID_DATA
 
+#define APP_LIB_SUBDIR         "app-lib/" // sub-directory under ANDROID_DATA
+
 #define MEDIA_SUBDIR           "media/" // sub-directory under ANDROID_DATA
 
 /* other handy constants */
@@ -93,6 +95,7 @@
 
 extern dir_rec_t android_app_dir;
 extern dir_rec_t android_app_private_dir;
+extern dir_rec_t android_app_lib_dir;
 extern dir_rec_t android_data_dir;
 extern dir_rec_t android_asec_dir;
 extern dir_rec_t android_media_dir;
@@ -207,4 +210,3 @@
 int dexopt(const char *apk_path, uid_t uid, int is_public);
 int movefiles();
 int linklib(const char* target, const char* source);
-int unlinklib(const char* libPath);
diff --git a/services/java/com/android/server/pm/Installer.java b/services/java/com/android/server/pm/Installer.java
index 4268ae0..85de349 100644
--- a/services/java/com/android/server/pm/Installer.java
+++ b/services/java/com/android/server/pm/Installer.java
@@ -369,10 +369,10 @@
      */
     public int linkNativeLibraryDirectory(String dataPath, String nativeLibPath) {
         if (dataPath == null) {
-            Slog.e(TAG, "unlinkNativeLibraryDirectory dataPath is null");
+            Slog.e(TAG, "linkNativeLibraryDirectory dataPath is null");
             return -1;
         } else if (nativeLibPath == null) {
-            Slog.e(TAG, "unlinkNativeLibraryDirectory nativeLibPath is null");
+            Slog.e(TAG, "linkNativeLibraryDirectory nativeLibPath is null");
             return -1;
         }
 
@@ -383,16 +383,4 @@
 
         return execute(builder.toString());
     }
-
-    public int unlinkNativeLibraryDirectory(String dataPath) {
-        if (dataPath == null) {
-            Slog.e(TAG, "unlinkNativeLibraryDirectory dataPath is null");
-            return -1;
-        }
-
-        StringBuilder builder = new StringBuilder("unlinklib ");
-        builder.append(dataPath);
-
-        return execute(builder.toString());
-    }
 }
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index b5ae214..e19a803 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -4468,9 +4468,11 @@
             throws IOException {
         if (!nativeLibraryDir.isDirectory()) {
             nativeLibraryDir.delete();
+
             if (!nativeLibraryDir.mkdir()) {
                 throw new IOException("Cannot create " + nativeLibraryDir.getPath());
             }
+
             try {
                 Libcore.os.chmod(nativeLibraryDir.getPath(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH
                         | S_IXOTH);
@@ -4478,6 +4480,8 @@
                 throw new IOException("Cannot chmod native library directory "
                         + nativeLibraryDir.getPath(), e);
             }
+        } else if (!SELinux.restorecon(nativeLibraryDir)) {
+            throw new IOException("Cannot set SELinux context for " + nativeLibraryDir.getPath());
         }
 
         /*