diff options
author | Duy Truong <duytruong@google.com> | 2022-01-28 00:36:28 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2022-01-28 00:36:28 +0000 |
commit | d7ceccad81a15a0acb51d92da74b636737a34799 (patch) | |
tree | 4f5c123868728eed61a5d3955803ad18c41bc564 | |
parent | 0511518253e2e9ccc20e5e2526cfe8c73a278501 (diff) | |
parent | f131819dfcbec6a34d4b1c31a2a848ce00cfab18 (diff) | |
download | platform_testing-d7ceccad81a15a0acb51d92da74b636737a34799.tar.gz |
Add library to use OverlayFS to make read-only partitions writable. am: f198453ca8 am: f131819dfc
Original change: https://googleplex-android-review.googlesource.com/c/platform/platform_testing/+/16740299
Change-Id: I74dbfc24d1fb5b159ed44e763374884eff2e84bf
-rw-r--r-- | libraries/sts-common-util/host-side/src/com/android/sts/common/OverlayFsUtils.java | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/libraries/sts-common-util/host-side/src/com/android/sts/common/OverlayFsUtils.java b/libraries/sts-common-util/host-side/src/com/android/sts/common/OverlayFsUtils.java new file mode 100644 index 000000000..f523fb7a4 --- /dev/null +++ b/libraries/sts-common-util/host-side/src/com/android/sts/common/OverlayFsUtils.java @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.sts.common; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.regex.Pattern; +import java.util.regex.Matcher; + +import com.android.tradefed.device.ITestDevice; +import com.android.tradefed.device.DeviceNotAvailableException; +import com.android.tradefed.util.CommandResult; +import com.android.tradefed.util.CommandStatus; + +public class OverlayFsUtils { + // output of `stat`, e.g. "root shell 755 u:object_r:vendor_file:s0" + static final Pattern PERM_PATTERN = + Pattern.compile( + "^(?<user>[a-zA-Z0-9_-]+) (?<group>[a-zA-Z0-9_-]+) (?<perm>[0-7]+)" + + " (?<secontext>.*)$"); + + /** + * Mounts an OverlayFS dir over the top most common dir in the list. + * + * <p>The directory should be writable after this returns successfully. To cleanup, reboot the + * device as unfortunately unmounting overlayfs is complicated. + * + * @param device The test device to setup overlayfs for. + * @param dir The directory to make writable. Directories with single quotes are not supported. + */ + public static void makeWritable(ITestDevice device, String dir) + throws DeviceNotAvailableException, IOException { + // TODO(duytruong): This should ideally be made into a TestRule that also handles cleanups + // However, test devices initiation is done in one of the @Before, after a rule's setup. + assertTrue("Can't acquire root for " + device.getSerialNumber(), device.enableAdbRoot()); + + String statOut = runAndCheck(device, "stat -c '%U %G %a %C' '" + dir + "'"); + Matcher m = PERM_PATTERN.matcher(statOut); + assertTrue("Bad stats output: " + statOut, m.find()); + String user = m.group("user"); + String group = m.group("group"); + String unixPerm = m.group("perm"); + String seContext = m.group("secontext"); + + Path tempdir = Paths.get("/mnt", "stsoverlayfs", dir); + String upperdir = tempdir.resolve("upper").toString(); + String workdir = tempdir.resolve("workdir").toString(); + + runAndCheck(device, String.format("mkdir -p '%s' '%s'", upperdir, workdir)); + runAndCheck(device, String.format("chown %s:%s '%s'", user, group, upperdir)); + runAndCheck(device, String.format("chcon '%s' '%s'", seContext, upperdir)); + runAndCheck(device, String.format("chmod %s '%s'", unixPerm, upperdir)); + + String mountCmd = + String.format( + "mount -t overlay overlay -o lowerdir='%s',upperdir='%s',workdir='%s' '%s'", + dir, upperdir, workdir, dir); + runAndCheck(device, mountCmd); + } + + /** + * Execute shell command on device, throws AssumptionViolatedException upon failure. + * + * @return stdout. + */ + private static String runAndCheck(ITestDevice device, String cmd) + throws DeviceNotAvailableException { + CommandResult res = device.executeShellV2Command(cmd); + String failMsg = + String.format( + "cmd failed: %s\ncode: %s\nstdout:\n%s\nstderr:\n%s", + cmd, res.getExitCode(), res.getStdout(), res.getStderr()); + assertEquals(failMsg, res.getStatus(), CommandStatus.SUCCESS); + return res.getStdout(); + } +} |