summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDuy Truong <duytruong@google.com>2022-01-28 00:36:28 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2022-01-28 00:36:28 +0000
commitd7ceccad81a15a0acb51d92da74b636737a34799 (patch)
tree4f5c123868728eed61a5d3955803ad18c41bc564
parent0511518253e2e9ccc20e5e2526cfe8c73a278501 (diff)
parentf131819dfcbec6a34d4b1c31a2a848ce00cfab18 (diff)
downloadplatform_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.java94
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();
+ }
+}