コード例 #1
0
ファイル: apexer.py プロジェクト: erfanoabdi/ErfanGSIs
def GenerateBuildInfo(args):
    build_info = apex_build_info_pb2.ApexBuildInfo()
    if (args.include_cmd_line_in_build_info):
        build_info.apexer_command_line = str(sys.argv)

    with open(args.file_contexts) as f:
        build_info.file_contexts = f.read()

    with open(args.canned_fs_config) as f:
        build_info.canned_fs_config = f.read()

    with open(args.android_manifest) as f:
        build_info.android_manifest = f.read()

    if args.target_sdk_version:
        build_info.target_sdk_version = args.target_sdk_version

    if args.min_sdk_version:
        build_info.min_sdk_version = args.min_sdk_version

    if args.no_hashtree:
        build_info.no_hashtree = True

    if args.override_apk_package_name:
        build_info.override_apk_package_name = args.override_apk_package_name

    if args.logging_parent:
        build_info.logging_parent = args.logging_parent

    if args.payload_type == 'image':
        build_info.payload_fs_type = args.payload_fs_type

    return build_info
コード例 #2
0
ファイル: apexer.py プロジェクト: erfanoabdi/ErfanGSIs
def ValidateArgs(args):
    build_info = None

    if args.build_info is not None:
        if not os.path.exists(args.build_info):
            print("Build info file '" + args.build_info + "' does not exist")
            return False
        with open(args.build_info) as buildInfoFile:
            build_info = apex_build_info_pb2.ApexBuildInfo()
            build_info.ParseFromString(buildInfoFile.read())

    if not os.path.exists(args.manifest):
        print("Manifest file '" + args.manifest + "' does not exist")
        return False

    if not os.path.isfile(args.manifest):
        print("Manifest file '" + args.manifest + "' is not a file")
        return False

    if args.android_manifest is not None:
        if not os.path.exists(args.android_manifest):
            print("Android Manifest file '" + args.android_manifest +
                  "' does not exist")
            return False

        if not os.path.isfile(args.android_manifest):
            print("Android Manifest file '" + args.android_manifest +
                  "' is not a file")
            return False
    elif build_info is not None:
        with tempfile.NamedTemporaryFile(delete=False) as temp:
            temp.write(build_info.android_manifest)
            args.android_manifest = temp.name

    if not os.path.exists(args.input_dir):
        print("Input directory '" + args.input_dir + "' does not exist")
        return False

    if not os.path.isdir(args.input_dir):
        print("Input directory '" + args.input_dir + "' is not a directory")
        return False

    if not args.force and os.path.exists(args.output):
        print(args.output + ' already exists. Use --force to overwrite.')
        return False

    if args.unsigned_payload_only:
        args.payload_only = True
        args.unsigned_payload = True

    if args.payload_type == 'image':
        if not args.key and not args.unsigned_payload:
            print('Missing --key {keyfile} argument!')
            return False

        if not args.file_contexts:
            if build_info is not None:
                with tempfile.NamedTemporaryFile(delete=False) as temp:
                    temp.write(build_info.file_contexts)
                    args.file_contexts = temp.name
            else:
                print(
                    'Missing --file_contexts {contexts} argument, or a --build_info argument!'
                )
                return False

        if not args.canned_fs_config:
            if not args.canned_fs_config:
                if build_info is not None:
                    with tempfile.NamedTemporaryFile(delete=False) as temp:
                        temp.write(build_info.canned_fs_config)
                        args.canned_fs_config = temp.name
                else:
                    print(
                        'Missing ----canned_fs_config {config} argument, or a --build_info argument!'
                    )
                    return False

    if not args.target_sdk_version:
        if build_info is not None:
            if build_info.target_sdk_version:
                args.target_sdk_version = build_info.target_sdk_version

    if not args.no_hashtree:
        if build_info is not None:
            if build_info.no_hashtree:
                args.no_hashtree = True

    if not args.min_sdk_version:
        if build_info is not None:
            if build_info.min_sdk_version:
                args.min_sdk_version = build_info.min_sdk_version

    if not args.override_apk_package_name:
        if build_info is not None:
            if build_info.override_apk_package_name:
                args.override_apk_package_name = build_info.override_apk_package_name

    if not args.logging_parent:
        if build_info is not None:
            if build_info.logging_parent:
                args.logging_parent = build_info.logging_parent

    return True
コード例 #3
0
def main(argv):
    args = parse_args(argv)
    apex_file_path = args.input

    container_files = get_container_files(apex_file_path, args.tmpdir)
    payload_dir = extract_payload_from_img(container_files['apex_payload.img'],
                                           args.tmpdir)
    libs = args.libs
    assert len(libs) > 0

    lib_paths = [
        os.path.join(payload_dir, lib_dir, lib)
        for lib_dir in ['lib', 'lib64'] for lib in libs
        if os.path.exists(os.path.join(payload_dir, lib_dir, lib))
    ]

    assert len(lib_paths) > 0

    lib_paths_hashes = [(lib, compute_sha512(lib)) for lib in lib_paths]

    if args.mode == 'strip':
        # Stripping mode. Add a reference to the version of libc++.so to the
        # requireSharedApexLibs entry in the manifest, and remove lib64/libc++.so
        # from the payload.
        pb = apex_manifest_pb2.ApexManifest()
        with open(container_files['apex_manifest.pb'], 'rb') as f:
            pb.ParseFromString(f.read())
            for lib_path_hash in lib_paths_hashes:
                basename = os.path.basename(lib_path_hash[0])
                libpath = _extract_lib_or_lib64(payload_dir, lib_path_hash[0])
                assert libpath in ('lib', 'lib64')
                pb.requireSharedApexLibs.append(
                    os.path.join(libpath, basename) + ':' + lib_path_hash[1])
                # Replace existing library with symlink
                symlink_dst = os.path.join('/', 'apex', 'sharedlibs', libpath,
                                           basename, lib_path_hash[1],
                                           basename)
                os.remove(lib_path_hash[0])
                os.system('ln -s {0} {1}'.format(symlink_dst,
                                                 lib_path_hash[0]))
            #
            # Example of resulting manifest:
            # ---
            # name: "com.android.apex.test.foo"
            # version: 1
            # requireNativeLibs: "libc.so"
            # requireNativeLibs: "libdl.so"
            # requireNativeLibs: "libm.so"
            # requireSharedApexLibs: "lib/libc++.so:23c5dd..."
            # requireSharedApexLibs: "lib/libsharedlibtest.so:870f38..."
            # requireSharedApexLibs: "lib64/libc++.so:72a584..."
            # requireSharedApexLibs: "lib64/libsharedlibtest.so:109015..."
            # --
            # To print uncomment the following:
            # from google.protobuf import text_format
            # print(text_format.MessageToString(pb))
        with open(container_files['apex_manifest.pb'], 'wb') as f:
            f.write(pb.SerializeToString())

    if args.mode == 'sharedlibs':
        # Sharedlibs mode. Mark in the APEX manifest that this package contains
        # shared libraries.
        pb = apex_manifest_pb2.ApexManifest()
        with open(container_files['apex_manifest.pb'], 'rb') as f:
            pb.ParseFromString(f.read())
            del pb.requireNativeLibs[:]
            pb.provideSharedApexLibs = True
        with open(container_files['apex_manifest.pb'], 'wb') as f:
            f.write(pb.SerializeToString())

        pb = apex_build_info_pb2.ApexBuildInfo()
        with open(container_files['apex_build_info.pb'], 'rb') as f:
            pb.ParseFromString(f.read())

        canned_fs_config = parse_fs_config(pb.canned_fs_config.decode('utf-8'))

        # Remove the bin directory from payload dir and from the canned_fs_config.
        shutil.rmtree(os.path.join(payload_dir, 'bin'))
        canned_fs_config = [
            config for config in canned_fs_config
            if not config[0].startswith('/bin')
        ]

        # Remove from the canned_fs_config the entries we are about to relocate in
        # different dirs.
        source_lib_paths = [
            os.path.join('/', libpath, lib) for libpath in ['lib', 'lib64']
            for lib in libs
        ]
        # We backup the fs config lines for the libraries we are going to relocate,
        # so we can set the same permissions later.
        canned_fs_config_original_lib = {
            config[0]: config
            for config in canned_fs_config if config[0] in source_lib_paths
        }

        canned_fs_config = [
            config for config in canned_fs_config
            if config[0] not in source_lib_paths
        ]

        # We move any targeted library in lib64/ or lib/ to a directory named
        # /lib64/libNAME.so/${SHA512_OF_LIBCPP}/ or
        # /lib/libNAME.so/${SHA512_OF_LIBCPP}/
        #
        for lib_path_hash in lib_paths_hashes:
            basename = os.path.basename(lib_path_hash[0])
            libpath = _extract_lib_or_lib64(payload_dir, lib_path_hash[0])
            tmp_lib = os.path.join(payload_dir, libpath, basename + '.bak')
            shutil.move(lib_path_hash[0], tmp_lib)
            destdir = os.path.join(payload_dir, libpath, basename,
                                   lib_path_hash[1])
            os.makedirs(destdir)
            shutil.move(tmp_lib, os.path.join(destdir, basename))

            canned_fs_config.append(
                ['/' + libpath + '/' + basename, '0', '2000', '0755'])
            canned_fs_config.append([
                '/' + libpath + '/' + basename + '/' + lib_path_hash[1], '0',
                '2000', '0755'
            ])

            if os.path.join('/', libpath,
                            basename) in canned_fs_config_original_lib:
                config = canned_fs_config_original_lib[os.path.join(
                    '/', libpath, basename)]
                canned_fs_config.append([
                    os.path.join('/', libpath, basename, lib_path_hash[1],
                                 basename), config[1], config[2], config[3]
                ])
            else:
                canned_fs_config.append([
                    os.path.join('/', libpath, basename, lib_path_hash[1],
                                 basename), '1000', '1000', '0644'
                ])

        pb.canned_fs_config = config_to_str(canned_fs_config).encode('utf-8')
        with open(container_files['apex_build_info.pb'], 'wb') as f:
            f.write(pb.SerializeToString())

    try:
        for lib in lib_paths:
            os.rmdir(os.path.dirname(lib))
    except OSError:
        # Directory not empty, that's OK.
        pass

    repack_apex_file_path = run_apexer(container_files, payload_dir, args.key,
                                       args.pubkey, args.tmpdir)

    resigned_apex_file_path = sign_apk_container(repack_apex_file_path,
                                                 args.x509key, args.pk8key,
                                                 args.tmpdir)

    shutil.copyfile(resigned_apex_file_path, args.output)