vogar: Add SshChrootTarget Make able `--ssh` and `--chroot` work together This change will help run libcore tests on VM in chroot env Test: none Change-Id: Ibf12940d87db88245f81b8364f958062239e3ae8
diff --git a/src/vogar/SshChrootTarget.java b/src/vogar/SshChrootTarget.java new file mode 100644 index 0000000..663cf23 --- /dev/null +++ b/src/vogar/SshChrootTarget.java
@@ -0,0 +1,115 @@ +/* + * Copyright (C) 2024 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 vogar; + +import com.google.common.collect.ImmutableList; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.List; +import java.util.ListIterator; + +public class SshChrootTarget extends SshTarget { + private final String chrootDir; + + private final String targetProcessWrapper; + + public SshChrootTarget(Log log, String hostAndPort, String chrootDir) { + super(log, hostAndPort); + this.chrootDir = chrootDir; + this.targetProcessWrapper = "unshare --user --map-root-user chroot " + chrootDir + " sh -c "; + } + + @Override + public void await(File directory) { + super.await(chrootToRoot(directory)); + } + + @Override + public List<File> ls(File directory) throws FileNotFoundException { + // Add chroot prefix to searched directory. + List<File> files = super.ls(chrootToRoot(directory)); + // Remove chroot prefix from files found in directory. + ListIterator<File> iterator = files.listIterator(); + while (iterator.hasNext()) { + File file = iterator.next(); + iterator.set(rootToChroot(file)); + } + return files; + } + + @Override + public void rm(File file) { + super.rm(chrootToRoot(file)); + } + + @Override + public void mkdirs(File file) { + super.mkdirs(chrootToRoot(file)); + } + + @Override + public void push(File local, File remote) { + super.push(local, chrootToRoot(remote)); + } + + @Override + public void pull(File remote, File local) { + super.pull(chrootToRoot(remote), local); + } + + @Override + protected ImmutableList<String> targetProcessPrefix() { + return super.targetProcessPrefix(); + } + + @Override + protected String targetProcessWrapper() { + return this.targetProcessWrapper; + } + + /** + * Convert a file relative to the chroot dir to a file relative to + * the device's filesystem "absolute" root. + */ + private File chrootToRoot(File file) { + return new File(chrootDir + "/" + file.getPath()); + } + + /** + * Convert a file relative to the device's filesystem "absolute" + * root to a file relative to the chroot dir . + */ + private File rootToChroot(File file) throws PathnameNotUnderChrootException { + String pathname = file.getPath(); + if (!pathname.startsWith(chrootDir)) { + throw new PathnameNotUnderChrootException(pathname, chrootDir); + } + return new File(pathname.substring(chrootDir.length())); + } + + /** + * Exception thrown when a pathname does not represent a file + * under the chroot directory. + */ + private static class PathnameNotUnderChrootException extends RuntimeException { + + public PathnameNotUnderChrootException(String pathname, String chrootDir) { + super("Pathname " + pathname + " does not represent a file under chroot directory " + + chrootDir); + } + } +}
diff --git a/src/vogar/SshTarget.java b/src/vogar/SshTarget.java index 94177db..58173e8 100644 --- a/src/vogar/SshTarget.java +++ b/src/vogar/SshTarget.java
@@ -30,7 +30,7 @@ /** * Runs actions on a remote host using SSH. */ -public final class SshTarget extends Target { +public class SshTarget extends Target { private final Log log; private final String host; private final int port;
diff --git a/src/vogar/Vogar.java b/src/vogar/Vogar.java index c2136e2..9a437a7 100644 --- a/src/vogar/Vogar.java +++ b/src/vogar/Vogar.java
@@ -676,7 +676,11 @@ } break; case SSH: - target = new SshTarget(console, sshHost); + if (chrootDir != null) { + target = new SshChrootTarget(console, sshHost, chrootDir); + } else { + target = new SshTarget(console, sshHost); + } break; case LOCAL: target = new LocalTarget(console, mkdir, rm);