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

Commit 1b0893ee authored by Jiyong Park's avatar Jiyong Park
Browse files

Build canned_fs_config using RuleBuilder

... in preparation for adding the support for custom canned fs config

Bug: 209971551
Test: m nothing
Change-Id: I7f2576ff99c65bdb6c9ce4ace61bc783eea2f0d4
parent 789e5026
Loading
Loading
Loading
Loading
+13 −14
Original line number Diff line number Diff line
@@ -2581,22 +2581,21 @@ func TestFilesInSubDir(t *testing.T) {
	`)

	generateFsRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("generateFsConfig")
	dirs := strings.Split(generateFsRule.Args["exec_paths"], " ")
	cmd := generateFsRule.RuleParams.Command

	// Ensure that the subdirectories are all listed
	ensureListContains(t, dirs, "etc")
	ensureListContains(t, dirs, "etc/foo")
	ensureListContains(t, dirs, "etc/foo/bar")
	ensureListContains(t, dirs, "lib64")
	ensureListContains(t, dirs, "lib64/foo")
	ensureListContains(t, dirs, "lib64/foo/bar")
	ensureListContains(t, dirs, "lib")
	ensureListContains(t, dirs, "lib/foo")
	ensureListContains(t, dirs, "lib/foo/bar")

	ensureListContains(t, dirs, "bin")
	ensureListContains(t, dirs, "bin/foo")
	ensureListContains(t, dirs, "bin/foo/bar")
	ensureContains(t, cmd, "/etc ")
	ensureContains(t, cmd, "/etc/foo ")
	ensureContains(t, cmd, "/etc/foo/bar ")
	ensureContains(t, cmd, "/lib64 ")
	ensureContains(t, cmd, "/lib64/foo ")
	ensureContains(t, cmd, "/lib64/foo/bar ")
	ensureContains(t, cmd, "/lib ")
	ensureContains(t, cmd, "/lib/foo ")
	ensureContains(t, cmd, "/lib/foo/bar ")
	ensureContains(t, cmd, "/bin ")
	ensureContains(t, cmd, "/bin/foo ")
	ensureContains(t, cmd, "/bin/foo/bar ")
}

func TestFilesInSubDirWhenNativeBridgeEnabled(t *testing.T) {
+59 −59
Original line number Diff line number Diff line
@@ -72,19 +72,6 @@ func init() {
}

var (
	// Create a canned fs config file where all files and directories are
	// by default set to (uid/gid/mode) = (1000/1000/0644)
	// TODO(b/113082813) make this configurable using config.fs syntax
	generateFsConfig = pctx.StaticRule("generateFsConfig", blueprint.RuleParams{
		Command: `( set -e; echo '/ 1000 1000 0755' ` +
			`&& for i in ${ro_paths}; do echo "/$$i 1000 1000 0644"; done ` +
			`&& for i in  ${exec_paths}; do echo "/$$i 0 2000 0755"; done ` +
			`&& ( tr ' ' '\n' <${out}.apklist | for i in ${apk_paths}; do read apk; echo "/$$i 0 2000 0755"; zipinfo -1 $$apk | sed "s:\(.*\):/$$i/\1 1000 1000 0644:"; done ) ) > ${out}`,
		Description:    "fs_config ${out}",
		Rspfile:        "$out.apklist",
		RspfileContent: "$in",
	}, "ro_paths", "exec_paths", "apk_paths")

	apexManifestRule = pctx.StaticRule("apexManifestRule", blueprint.RuleParams{
		Command: `rm -f $out && ${jsonmodify} $in ` +
			`-a provideNativeLibs ${provideNativeLibs} ` +
@@ -583,55 +570,11 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) {
	// Figure out if need to compress apex.
	compressionEnabled := ctx.Config().CompressedApex() && proptools.BoolDefault(a.properties.Compressible, false) && !a.testApex && !ctx.Config().UnbundledBuildApps()
	if apexType == imageApex {

		////////////////////////////////////////////////////////////////////////////////////
		// Step 2: create canned_fs_config which encodes filemode,uid,gid of each files
		// in this APEX. The file will be used by apexer in later steps.
		// TODO(jiyong): make this as a function
		// TODO(jiyong): use the RuleBuilder
		var readOnlyPaths = []string{"apex_manifest.json", "apex_manifest.pb"}
		var executablePaths []string // this also includes dirs
		var extractedAppSetPaths android.Paths
		var extractedAppSetDirs []string
		for _, f := range a.filesInfo {
			pathInApex := f.path()
			if f.installDir == "bin" || strings.HasPrefix(f.installDir, "bin/") {
				executablePaths = append(executablePaths, pathInApex)
				for _, d := range f.dataPaths {
					readOnlyPaths = append(readOnlyPaths, filepath.Join(f.installDir, d.RelativeInstallPath, d.SrcPath.Rel()))
				}
				for _, s := range f.symlinks {
					executablePaths = append(executablePaths, filepath.Join(f.installDir, s))
				}
			} else if f.class == appSet {
				extractedAppSetPaths = append(extractedAppSetPaths, f.builtFile)
				extractedAppSetDirs = append(extractedAppSetDirs, f.installDir)
			} else {
				readOnlyPaths = append(readOnlyPaths, pathInApex)
			}
			dir := f.installDir
			for !android.InList(dir, executablePaths) && dir != "" {
				executablePaths = append(executablePaths, dir)
				dir, _ = filepath.Split(dir) // move up to the parent
				if len(dir) > 0 {
					// remove trailing slash
					dir = dir[:len(dir)-1]
				}
			}
		}
		sort.Strings(readOnlyPaths)
		sort.Strings(executablePaths)
		cannedFsConfig := android.PathForModuleOut(ctx, "canned_fs_config")
		ctx.Build(pctx, android.BuildParams{
			Rule:        generateFsConfig,
			Output:      cannedFsConfig,
			Description: "generate fs config",
			Inputs:      extractedAppSetPaths,
			Args: map[string]string{
				"ro_paths":   strings.Join(readOnlyPaths, " "),
				"exec_paths": strings.Join(executablePaths, " "),
				"apk_paths":  strings.Join(extractedAppSetDirs, " "),
			},
		})
		cannedFsConfig := a.buildCannedFsConfig(ctx)
		implicitInputs = append(implicitInputs, cannedFsConfig)

		////////////////////////////////////////////////////////////////////////////////////
@@ -1072,3 +1015,60 @@ func (a *apexBundle) buildLintReports(ctx android.ModuleContext) {

	a.lintReports = java.BuildModuleLintReportZips(ctx, depSetsBuilder.Build())
}

func (a *apexBundle) buildCannedFsConfig(ctx android.ModuleContext) android.OutputPath {
	var readOnlyPaths = []string{"apex_manifest.json", "apex_manifest.pb"}
	var executablePaths []string // this also includes dirs
	var appSetDirs []string
	appSetFiles := make(map[string]android.Path)
	for _, f := range a.filesInfo {
		pathInApex := f.path()
		if f.installDir == "bin" || strings.HasPrefix(f.installDir, "bin/") {
			executablePaths = append(executablePaths, pathInApex)
			for _, d := range f.dataPaths {
				readOnlyPaths = append(readOnlyPaths, filepath.Join(f.installDir, d.RelativeInstallPath, d.SrcPath.Rel()))
			}
			for _, s := range f.symlinks {
				executablePaths = append(executablePaths, filepath.Join(f.installDir, s))
			}
		} else if f.class == appSet {
			appSetDirs = append(appSetDirs, f.installDir)
			appSetFiles[f.installDir] = f.builtFile
		} else {
			readOnlyPaths = append(readOnlyPaths, pathInApex)
		}
		dir := f.installDir
		for !android.InList(dir, executablePaths) && dir != "" {
			executablePaths = append(executablePaths, dir)
			dir, _ = filepath.Split(dir) // move up to the parent
			if len(dir) > 0 {
				// remove trailing slash
				dir = dir[:len(dir)-1]
			}
		}
	}
	sort.Strings(readOnlyPaths)
	sort.Strings(executablePaths)
	sort.Strings(appSetDirs)

	cannedFsConfig := android.PathForModuleOut(ctx, "canned_fs_config")
	builder := android.NewRuleBuilder(pctx, ctx)
	cmd := builder.Command()
	cmd.Text("(")
	cmd.Text("echo '/ 1000 1000 0755';")
	for _, p := range readOnlyPaths {
		cmd.Textf("echo '/%s 1000 1000 0644';", p)
	}
	for _, p := range executablePaths {
		cmd.Textf("echo '/%s 0 2000 0755';", p)
	}
	for _, dir := range appSetDirs {
		cmd.Textf("echo '/%s 0 2000 0755';", dir)
		file := appSetFiles[dir]
		cmd.Text("zipinfo -1").Input(file).Textf(`| sed "s:\(.*\):/%s/\1 1000 1000 0644:";`, dir)
	}
	cmd.Text(")").FlagWithOutput("> ", cannedFsConfig)
	builder.Build("generateFsConfig", fmt.Sprintf("Generating canned fs config for %s", a.BaseModuleName()))

	return cannedFsConfig.OutputPath
}