Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions adb_cli/src/models/adb_cli_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ impl From<adb_client::RustADBError> for ADBCliError {
let value = Box::new(value);

match value.as_ref() {
// List of [`RustADBError`] that may need an issue as abnormal
RustADBError::RegexParsingError
| RustADBError::WrongResponseReceived(_, _)
| RustADBError::FramebufferImageError(_)
Expand Down Expand Up @@ -68,8 +67,8 @@ impl From<adb_client::RustADBError> for ADBCliError {
| RustADBError::MDNSError(_)
| RustADBError::SendError
| RustADBError::UnknownFileMode(_)
| RustADBError::UnknownTransport(_) => Self::MayNeedAnIssue(value),
// List of [`RustADBError`] that may occur in standard contexts and therefore do not require for issues
| RustADBError::UnknownTransport(_)
| RustADBError::RemountError(_) => Self::MayNeedAnIssue(value),
RustADBError::ADBDeviceNotPaired
| RustADBError::UnknownResponseType(_)
| RustADBError::DeviceNotFound(_)
Expand Down
11 changes: 10 additions & 1 deletion adb_client/src/adb_device_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::path::Path;

use image::{ImageBuffer, ImageFormat, Rgba};

use crate::models::{ADBListItemType, AdbStatResponse};
use crate::models::{ADBListItemType, AdbStatResponse, RemountInfo};
use crate::{RebootType, Result};

/// Trait representing all features available on ADB devices.
Expand All @@ -30,6 +30,9 @@ pub trait ADBDeviceExt {
/// Reboot the device using given reboot type
fn reboot(&mut self, reboot_type: RebootType) -> Result<()>;

/// Remount the device partitions as read-write
fn remount(&mut self) -> Result<Vec<RemountInfo>>;

/// Run `activity` from `package` on device. Return the command output.
fn run_activity(
&mut self,
Expand Down Expand Up @@ -60,6 +63,12 @@ pub trait ADBDeviceExt {
/// Uninstall the package `package` from device.
fn uninstall(&mut self, package: &dyn AsRef<str>) -> Result<()>;

/// Enable dm-verity on the device
fn enable_verity(&mut self) -> Result<()>;

/// Disable dm-verity on the device
fn disable_verity(&mut self) -> Result<()>;

/// Inner method requesting framebuffer from an Android device
fn framebuffer_inner(&mut self) -> Result<ImageBuffer<Rgba<u8>, Vec<u8>>>;

Expand Down
3 changes: 3 additions & 0 deletions adb_client/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ pub enum RustADBError {
/// Indicates that the device must be paired before attempting a connection over WI-FI
#[error("Device not paired before attempting to connect")]
ADBDeviceNotPaired,
/// Indicates that remount operation failed
#[error("Cannot remount filesystem: {0}")]
RemountError(String),
/// An error occurred when getting device's framebuffer image
#[error(transparent)]
FramebufferImageError(#[from] image::error::ImageError),
Expand Down
17 changes: 16 additions & 1 deletion adb_client/src/message_devices/adb_message_device_commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::{
message_devices::{
adb_message_device::ADBMessageDevice, adb_message_transport::ADBMessageTransport,
},
models::AdbStatResponse,
models::{AdbStatResponse, RemountInfo},
};
use std::{
io::{Read, Write},
Expand Down Expand Up @@ -41,6 +41,11 @@ impl<T: ADBMessageTransport> ADBDeviceExt for ADBMessageDevice<T> {
self.reboot(reboot_type)
}

#[inline]
fn remount(&mut self) -> Result<Vec<RemountInfo>> {
self.remount()
}

#[inline]
fn install(&mut self, apk_path: &dyn AsRef<Path>) -> Result<()> {
self.install(apk_path)
Expand All @@ -51,6 +56,16 @@ impl<T: ADBMessageTransport> ADBDeviceExt for ADBMessageDevice<T> {
self.uninstall(package)
}

#[inline]
fn enable_verity(&mut self) -> Result<()> {
self.enable_verity()
}

#[inline]
fn disable_verity(&mut self) -> Result<()> {
self.disable_verity()
}

#[inline]
fn framebuffer_inner(&mut self) -> Result<image::ImageBuffer<image::Rgba<u8>, Vec<u8>>> {
self.framebuffer_inner()
Expand Down
2 changes: 2 additions & 0 deletions adb_client/src/message_devices/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ mod list;
mod pull;
mod push;
mod reboot;
mod remount;
mod shell;
mod stat;
mod uninstall;
mod utils;
mod verity;
34 changes: 34 additions & 0 deletions adb_client/src/message_devices/commands/remount.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use crate::{
Result,
message_devices::{
adb_message_device::ADBMessageDevice, adb_message_transport::ADBMessageTransport,
message_commands::MessageCommand,
},
models::RemountInfo,
};

impl<T: ADBMessageTransport> ADBMessageDevice<T> {
pub(crate) fn remount(&mut self) -> Result<Vec<RemountInfo>> {
self.open_session(b"remount:\0")?;

let response = self.get_transport_mut().read_message()?;

response.assert_command(MessageCommand::Okay)?;

let mut response_str: Vec<String> = Vec::new();
loop {
let response = self.get_transport_mut().read_message()?;

if response.header().command() != MessageCommand::Write {
break;
}

let payload_str = String::from_utf8_lossy(response.payload());
let payload_str = payload_str.trim();

response_str.push(payload_str.to_string());
}

RemountInfo::from_str_response(&response_str.join("\n"))
}
}
25 changes: 25 additions & 0 deletions adb_client/src/message_devices/commands/verity.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use crate::{
Result,
message_devices::{
adb_message_device::ADBMessageDevice, adb_message_transport::ADBMessageTransport,
message_commands::MessageCommand,
},
};

impl<T: ADBMessageTransport> ADBMessageDevice<T> {
pub(crate) fn enable_verity(&mut self) -> Result<()> {
self.open_session(b"enable-verity:\0")?;

self.get_transport_mut()
.read_message()
.and_then(|message| message.assert_command(MessageCommand::Okay))
}

pub(crate) fn disable_verity(&mut self) -> Result<()> {
self.open_session(b"disable-verity:\0")?;

self.get_transport_mut()
.read_message()
.and_then(|message| message.assert_command(MessageCommand::Okay))
}
}
16 changes: 16 additions & 0 deletions adb_client/src/message_devices/tcp/adb_tcp_device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::message_devices::adb_message_transport::ADBMessageTransport;
use crate::message_devices::adb_transport_message::ADBTransportMessage;
use crate::message_devices::message_commands::MessageCommand;
use crate::message_devices::models::{ADBRsaKey, read_adb_private_key};
use crate::models::RemountInfo;
use crate::tcp::tcp_transport::TcpTransport;
use crate::utils::get_default_adb_key_path;
use crate::{ADBDeviceExt, ADBListItemType, ADBTransport, Result};
Expand Down Expand Up @@ -130,6 +131,11 @@ impl ADBDeviceExt for ADBTcpDevice {
self.inner.reboot(reboot_type)
}

#[inline]
fn remount(&mut self) -> Result<Vec<RemountInfo>> {
self.inner.remount()
}

#[inline]
fn install(&mut self, apk_path: &dyn AsRef<Path>) -> Result<()> {
self.inner.install(apk_path)
Expand All @@ -140,6 +146,16 @@ impl ADBDeviceExt for ADBTcpDevice {
self.inner.uninstall(package)
}

#[inline]
fn enable_verity(&mut self) -> Result<()> {
self.inner.enable_verity()
}

#[inline]
fn disable_verity(&mut self) -> Result<()> {
self.inner.disable_verity()
}

#[inline]
fn framebuffer_inner(&mut self) -> Result<image::ImageBuffer<image::Rgba<u8>, Vec<u8>>> {
self.inner.framebuffer_inner()
Expand Down
16 changes: 16 additions & 0 deletions adb_client/src/message_devices/usb/adb_usb_device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use crate::message_devices::adb_transport_message::ADBTransportMessage;
use crate::message_devices::message_commands::MessageCommand;
use crate::message_devices::models::ADBRsaKey;
use crate::message_devices::models::read_adb_private_key;
use crate::models::RemountInfo;
use crate::usb::usb_transport::USBTransport;
use crate::utils::get_default_adb_key_path;

Expand Down Expand Up @@ -264,6 +265,11 @@ impl ADBDeviceExt for ADBUSBDevice {
self.inner.reboot(reboot_type)
}

#[inline]
fn remount(&mut self) -> Result<Vec<RemountInfo>> {
self.inner.remount()
}

#[inline]
fn install(&mut self, apk_path: &dyn AsRef<Path>) -> Result<()> {
self.inner.install(apk_path)
Expand All @@ -274,6 +280,16 @@ impl ADBDeviceExt for ADBUSBDevice {
self.inner.uninstall(package)
}

#[inline]
fn enable_verity(&mut self) -> Result<()> {
self.inner.enable_verity()
}

#[inline]
fn disable_verity(&mut self) -> Result<()> {
self.inner.disable_verity()
}

#[inline]
fn framebuffer_inner(&mut self) -> Result<image::ImageBuffer<image::Rgba<u8>, Vec<u8>>> {
self.inner.framebuffer_inner()
Expand Down
4 changes: 3 additions & 1 deletion adb_client/src/models/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ mod framebuffer_info;
mod host_features;
mod list_info;
mod reboot_type;
mod remount_info;
mod sync_command;

pub(crate) use adb_request_status::AdbRequestStatus;
Expand All @@ -12,4 +13,5 @@ pub(crate) use framebuffer_info::{FrameBufferInfoV1, FrameBufferInfoV2};
pub use host_features::HostFeatures;
pub use list_info::{ADBListItem, ADBListItemType};
pub use reboot_type::RebootType;
pub(crate) use sync_command::SyncCommand;
pub use remount_info::RemountInfo;
pub use sync_command::SyncCommand;
54 changes: 54 additions & 0 deletions adb_client/src/models/remount_info.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use std::{str::FromStr, sync::LazyLock};

use regex::Regex;

use crate::{Result, RustADBError};

static REMOUNT_REGEX: LazyLock<Regex> = LazyLock::new(|| {
Regex::new(r"^Using\s+(?P<path>\S+)\s+for\s+(?P<mode>\S+)$").expect("Invalid remount regex")
});

#[derive(Debug)]
/// Information about remount operation
pub struct RemountInfo {
/// Path that was remounted
pub path: String,
/// Mode that was used for remounting
pub mode: String,
}

impl FromStr for RemountInfo {
type Err = RustADBError;

fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
let caps = REMOUNT_REGEX
.captures(s)
.ok_or_else(|| RustADBError::RemountError(s.to_string()))?;

let (Some(path), Some(mode)) = (caps.name("path"), caps.name("mode")) else {
return Err(RustADBError::RemountError(s.to_string()));
};

Ok(RemountInfo {
path: path.as_str().to_string(),
mode: mode.as_str().to_string(),
})
}
}

impl RemountInfo {
pub(crate) fn from_str_response(s: &str) -> Result<Vec<Self>> {
if !s.ends_with("remount succeeded") {
return Err(RustADBError::RemountError(s.to_string()));
}

let mut infos = Vec::new();
for line in s.lines() {
if line.starts_with("Using") {
infos.push(Self::from_str(line)?);
}
}

Ok(infos)
}
}
6 changes: 6 additions & 0 deletions adb_client/src/server/adb_server_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ pub(crate) enum AdbServerCommand {
Reverse(String, String),
ReverseRemoveAll,
Reconnect,
Remount,
DisableVerity,
EnableVerity,
TcpIp(u16),
Usb,
}
Expand Down Expand Up @@ -88,6 +91,9 @@ impl Display for AdbServerCommand {
AdbServerCommand::ServerStatus => write!(f, "host:server-status"),
AdbServerCommand::Reconnect => write!(f, "reconnect"),
AdbServerCommand::ReconnectOffline => write!(f, "host:reconnect-offline"),
AdbServerCommand::Remount => write!(f, "remount:"),
AdbServerCommand::DisableVerity => write!(f, "disable-verity:"),
AdbServerCommand::EnableVerity => write!(f, "enable-verity:"),
AdbServerCommand::TcpIp(port) => {
write!(f, "tcpip:{port}")
}
Expand Down
17 changes: 16 additions & 1 deletion adb_client/src/server_device/adb_server_device_commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::{

use crate::{
ADBDeviceExt, ADBListItemType, Result, RustADBError,
models::{AdbStatResponse, HostFeatures},
models::{AdbStatResponse, HostFeatures, RemountInfo},
server::AdbServerCommand,
};

Expand Down Expand Up @@ -125,6 +125,21 @@ impl ADBDeviceExt for ADBServerDevice {
self.reboot(reboot_type)
}

#[inline]
fn remount(&mut self) -> Result<Vec<RemountInfo>> {
self.remount()
}

#[inline]
fn enable_verity(&mut self) -> Result<()> {
self.enable_verity()
}

#[inline]
fn disable_verity(&mut self) -> Result<()> {
self.disable_verity()
}

#[inline]
fn push(&mut self, stream: &mut dyn Read, path: &dyn AsRef<str>) -> Result<()> {
self.push(stream, path)
Expand Down
2 changes: 2 additions & 0 deletions adb_client/src/server_device/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ mod logcat;
mod reboot;
mod reconnect;
mod recv;
mod remount;
mod reverse;
mod send;
mod stat;
mod tcpip;
mod transport;
mod uninstall;
mod usb;
mod verity;
20 changes: 20 additions & 0 deletions adb_client/src/server_device/commands/remount.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use crate::{
Result, models::RemountInfo, server::AdbServerCommand, server_device::ADBServerDevice,
};
use std::io::Read;

impl ADBServerDevice {
/// Remounts the device filesystem as read-write
pub fn remount(&mut self) -> Result<Vec<RemountInfo>> {
self.set_serial_transport()?;

self.transport
.send_adb_request(&AdbServerCommand::Remount)?;

let mut data = [0; 1024];
let read_amount = self.transport.get_raw_connection()?.read(&mut data)?;

let response = String::from_utf8_lossy(&data[0..read_amount]);
RemountInfo::from_str_response(&response)
}
}
Loading
Loading