Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0689b60b authored by Kenny Root's avatar Kenny Root Committed by Android Git Automerger
Browse files

am 54e01e0f: Merge "Symlink application lib directory when on SD card" into gingerbread

Merge commit '54e01e0f' into gingerbread-plus-aosp

* commit '54e01e0f':
  Symlink application lib directory when on SD card
parents ea445758 54e01e0f
Loading
Loading
Loading
Loading
+154 −0
Original line number Diff line number Diff line
@@ -936,3 +936,157 @@ int movefiles()
done:
    return 0;
}

int linklib(const char* dataDir, const char* asecLibDir)
{
    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) {
        LOGE("library dir len too large");
        rc = -1;
        goto out;
    }

    if (snprintf(libdir, sizeof(libdir), "%s%s", dataDir, PKG_LIB_POSTFIX) != (ssize_t)libdirLen) {
        LOGE("library dir not written successfully: %s\n", strerror(errno));
        rc = -1;
        goto out;
    }

    if (stat(dataDir, &s) < 0) return -1;

    if (chown(dataDir, 0, 0) < 0) {
        LOGE("failed to chown '%s': %s\n", dataDir, strerror(errno));
        return -1;
    }

    if (chmod(dataDir, 0700) < 0) {
        LOGE("failed to chmod '%s': %s\n", dataDir, strerror(errno));
        rc = -1;
        goto out;
    }

    if (lstat(libdir, &libStat) < 0) {
        LOGE("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 (symlink(asecLibDir, libdir) < 0) {
        LOGE("couldn't symlink directory '%s' -> '%s': %s\n", libdir, asecLibDir, strerror(errno));
        rc = -errno;
        goto out;
    }

    if (lchown(libdir, AID_SYSTEM, AID_SYSTEM) < 0) {
        LOGE("cannot chown dir '%s': %s\n", libdir, strerror(errno));
        unlink(libdir);
        rc = -errno;
        goto out;
    }

out:
    if (chmod(dataDir, s.st_mode) < 0) {
        LOGE("failed to chmod '%s': %s\n", dataDir, strerror(errno));
        return -errno;
    }

    if (chown(dataDir, s.st_uid, s.st_gid) < 0) {
        LOGE("failed to chown '%s' : %s\n", dataDir, strerror(errno));
        return -errno;
    }

    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) {
        LOGE("library dir not written successfully: %s\n", strerror(errno));
        return -1;
    }

    if (stat(dataDir, &s) < 0) {
        LOGE("couldn't state data dir");
        return -1;
    }

    if (chown(dataDir, 0, 0) < 0) {
        LOGE("failed to chown '%s': %s\n", dataDir, strerror(errno));
        return -1;
    }

    if (chmod(dataDir, 0700) < 0) {
        LOGE("failed to chmod '%s': %s\n", dataDir, strerror(errno));
        rc = -1;
        goto out;
    }

    if (lstat(libdir, &libStat) < 0) {
        LOGE("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) {
        LOGE("cannot create dir '%s': %s\n", libdir, strerror(errno));
        rc = -errno;
        goto out;
    }

    if (chown(libdir, AID_SYSTEM, AID_SYSTEM) < 0) {
        LOGE("cannot chown dir '%s': %s\n", libdir, strerror(errno));
        unlink(libdir);
        rc = -errno;
        goto out;
    }

out:
    if (chmod(dataDir, s.st_mode) < 0) {
        LOGE("failed to chmod '%s': %s\n", dataDir, strerror(errno));
        return -1;
    }

    if (chown(dataDir, s.st_uid, s.st_gid) < 0) {
        LOGE("failed to chown '%s' : %s\n", dataDir, strerror(errno));
        return -1;
    }

    return rc;
}
+12 −0
Original line number Diff line number Diff line
@@ -101,6 +101,16 @@ static int do_movefiles(char **arg, char reply[REPLY_MAX])
    return movefiles();
}

static int do_linklib(char **arg, char reply[REPLY_MAX])
{
    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;
@@ -121,6 +131,8 @@ struct cmdinfo cmds[] = {
    { "getsize",              4, do_get_size },
    { "rmuserdata",           2, do_rm_user_data },
    { "movefiles",            0, do_movefiles },
    { "linklib",              2, do_linklib },
    { "unlinklib",            1, do_unlinklib },
};

static int readx(int s, void *_buf, int count)
+2 −0
Original line number Diff line number Diff line
@@ -111,3 +111,5 @@ int get_size(const char *pkgname, const char *apkpath, const char *fwdlock_apkpa
int free_cache(int64_t free_size);
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);
+39 −5
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ import android.util.DisplayMetrics;
import android.util.Log;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;

public class PackageManagerTests extends AndroidTestCase {
@@ -378,6 +379,18 @@ public class PackageManagerTests extends AndroidTestCase {
                    assertEquals(publicSrcPath, appInstallPath);
                    assertFalse((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
                    assertTrue(info.nativeLibraryDir.startsWith(dataDir.getPath()));

                    // Make sure the native library dir is not a symlink
                    final File nativeLibDir = new File(info.nativeLibraryDir);
                    assertTrue("Native library dir should exist at " + info.nativeLibraryDir,
                            nativeLibDir.exists());
                    try {
                        assertEquals("Native library dir should not be a symlink",
                                info.nativeLibraryDir,
                                nativeLibDir.getCanonicalPath());
                    } catch (IOException e) {
                        fail("Can't read " + nativeLibDir.getPath());
                    }
                } else if (rLoc == INSTALL_LOC_SD){
                    assertTrue("Application flags (" + info.flags
                            + ") should contain FLAG_EXTERNAL_STORAGE",
@@ -391,6 +404,19 @@ public class PackageManagerTests extends AndroidTestCase {
                    assertTrue("The native library path (" + info.nativeLibraryDir
                            + ") should start with " + SECURE_CONTAINERS_PREFIX,
                            info.nativeLibraryDir.startsWith(SECURE_CONTAINERS_PREFIX));

                    // Make sure the native library in /data/data/<app>/lib is a
                    // symlink to the ASEC
                    final File nativeLibSymLink = new File(info.dataDir, "lib");
                    assertTrue("Native library symlink should exist at " + nativeLibSymLink.getPath(),
                            nativeLibSymLink.exists());
                    try {
                        assertEquals(nativeLibSymLink.getPath() + " should be a symlink to "
                                + info.nativeLibraryDir, info.nativeLibraryDir, nativeLibSymLink
                                .getCanonicalPath());
                    } catch (IOException e) {
                        fail("Can't read " + nativeLibSymLink.getPath());
                    }
                } else {
                    // TODO handle error. Install should have failed.
                    fail("Install should have failed");
@@ -1406,13 +1432,21 @@ public class PackageManagerTests extends AndroidTestCase {
                        receiver);
                assertTrue(retCode);
                ApplicationInfo info = getPm().getApplicationInfo(ip.pkg.packageName, 0);
                assertNotNull(info);
                assertNotNull("ApplicationInfo for recently installed application should exist",
                        info);
                if ((moveFlags & PackageManager.MOVE_INTERNAL) != 0) {
                    assertTrue((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) == 0);
                    assertTrue(info.nativeLibraryDir.startsWith(info.dataDir));
                    assertTrue("ApplicationInfo.FLAG_EXTERNAL_STORAGE flag should NOT be set",
                            (info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) == 0);
                    assertTrue("ApplicationInfo.nativeLibraryDir should start with " + info.dataDir,
                            info.nativeLibraryDir.startsWith(info.dataDir));
                } else if ((moveFlags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0){
                    assertTrue((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
                    assertTrue(info.nativeLibraryDir.startsWith(SECURE_CONTAINERS_PREFIX));
                    assertTrue("ApplicationInfo.FLAG_EXTERNAL_STORAGE flag should be set",
                            (info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
                    assertTrue("ApplicationInfo.nativeLibraryDir should start with " + SECURE_CONTAINERS_PREFIX,
                            info.nativeLibraryDir.startsWith(SECURE_CONTAINERS_PREFIX));
                    final File nativeLibSymLink = new File(info.dataDir, "lib");
                    assertTrue("The data directory should have a 'lib' symlink that points to the ASEC container",
                            nativeLibSymLink.getCanonicalPath().startsWith(SECURE_CONTAINERS_PREFIX));
                }
            }
        } catch (NameNotFoundException e) {
+29 −0
Original line number Diff line number Diff line
@@ -327,4 +327,33 @@ class Installer {
    public int moveFiles() {
        return execute("movefiles");
    }

    public int linkNativeLibraryDirectory(String dataPath, String nativeLibPath) {
        if (dataPath == null) {
            Slog.e(TAG, "unlinkNativeLibraryDirectory dataPath is null");
            return -1;
        } else if (nativeLibPath == null) {
            Slog.e(TAG, "unlinkNativeLibraryDirectory nativeLibPath is null");
            return -1;
        }

        StringBuilder builder = new StringBuilder("linklib ");
        builder.append(dataPath);
        builder.append(' ');
        builder.append(nativeLibPath);

        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());
    }
}
Loading