Вопрос или проблема
Я пытаюсь создать образ диска для флеширования на Rust. Чтобы получить доступ к SD-карте, я пытаюсь использовать authopen, как описано в предыдущем ответе.
Вот небольшой пример кода на Rust, который я создал для воспроизведения проблемы:
use std::{
io::{Write, IoSliceMut},
process::{Command, Stdio},
};
use security_framework::authorization::{Authorization, AuthorizationItemSetBuilder, Flags};
use nix::sys::socket::{socketpair, SockFlag, SockType, AddressFamily, recvmsg, MsgFlags, UnixAddr, RecvMsg};
use nix::unistd::{close, pipe};
use nix::cmsg_space;
const DISK: &str = "/dev/rdisk3";
fn main() {
open_auth(DISK);
}
fn open_auth(path: &str) {
let rights = AuthorizationItemSetBuilder::new()
.add_right(format!("sys.openfile.readwrite.{}", path))
.unwrap()
.build();
let auth = Authorization::new(
Some(rights),
None,
Flags::INTERACTION_ALLOWED | Flags::EXTEND_RIGHTS | Flags::PREAUTHORIZE,
)
.unwrap();
let form = auth.make_external_form().unwrap();
let form_bytes: Vec<u8> = form.bytes.into_iter().map(|x| x as u8).collect();
let (srx, stx) = socketpair(
AddressFamily::Unix,
SockType::Stream,
None,
SockFlag::empty(),
)
.unwrap();
let (prx, ptx) = pipe().unwrap();
let mut cmd = Command::new("/usr/libexec/authopen")
.args(["-stdoutpipe", "-extauth", "-o", "02", path])
.stdin(Stdio::piped())
.stdout(stx)
.spawn()
.unwrap();
let mut stdin = cmd.stdin.take().unwrap();
stdin.write_all(&form_bytes).unwrap();
drop(stdin);
let mut buf = [0u8; 4];
let mut io_vec = [IoSliceMut::new(&mut buf)];
let mut cmsg = cmsg_space!(RawFd);
println!("Размер: {}", cmsg.capacity());
let msg: RecvMsg<'_, '_, UnixAddr> = recvmsg(
srx.as_raw_fd(),
&mut io_vec,
Some(&mut cmsg),
MsgFlags::empty(),
)
.unwrap();
println!("RMSG: {:?}", msg);
println!("Что-то: {:?}", msg.cmsgs().unwrap().collect::<Vec<_>>());
println!("CMSG: {:?}", cmsg);
println!("IOVEC: {:?}", io_vec);
let output = cmd.wait().unwrap();
println!("Сырой вывод: {output:#?}");
}
Вот вывод, который я получаю, когда пытаюсь запустить его:
Завершено dev profile [неоптимизированный + отладочная информация] цель(и) за 1.26s
Запуск target/debug/temp
Размер: 16
authopen: /dev/rdisk3: Нет такого файла или директории
RMSG: RecvMsg { bytes: 2, cmsghdr: None, address: Some(UnixAddr { sun: sockaddr_un { sun_len: 0, sun_family: 0 } }), flags: MsgFlags(0x0), iobufs: PhantomData<&()>, mhdr: msghdr { msg_name: 0x7ff7b6161196, msg_namelen: 0, msg_iov: 0x7ff7b6161b98, msg_iovlen: 1, msg_control: 0x7fa2960040d0, msg_controllen: 0, msg_flags: 0 } }
Что-то: []
CMSG: []
IOVEC: [[0, 2, 0, 0]]
Сырой вывод: ExitStatus(
unix_wait_status(
256,
),
)
Как вы видите, ответ, который я получаю, похоже, неправильный. Я ожидал получить контрольное сообщение ScmRights
, но получил лишь 2 байта ответа.
Я не занимался разработкой на macOS ранее, так что, возможно, я просто делаю что-то не так. Буду признателен за любую помощь.
Ответ или решение
Для того чтобы правильно реализовать предварительное авторизованное открытие (pre-authorize) с использованием authopen
в Rust, необходимо учесть несколько моментов, которые могли вызвать проблему в вашем коде. Давайте разберем основные шаги, которые помогут исправить вашу реализацию и добиться желаемого результата.
Шаг 1: Проверка пути к устройству
Первым делом, убедитесь, что путь к устройству /dev/rdisk3
действительно существует и вы можете к нему обратиться. Вы можете проверить это с помощью команды в терминале:
ls /dev/rdisk3
Если устройство не найдено, это может объяснить ошибку authopen: /dev/rdisk3: No such file or directory
.
Шаг 2: Проверка прав доступа
Проверьте, есть ли у вашей программы достаточные права на доступ к файлу или устройству. Для работы с authopen
, необходимо, чтобы у вас были соответствующие права на управление подключаемыми устройствами, такие как SD-карты.
Шаг 3: Исправление кода для управления сокетами
Ваш код по работе с сокетами имеет несколько неточностей. Вам нужно правильно устанавливать и обрабатывать передачу прав. Кроме того, стоит проверить, что в момент отправки данных через сокет, контролируемые сообщения корректны. Ниже приведен исправленный фрагмент кода:
use std::{
io::{Write, IoSliceMut},
process::{Command, Stdio},
};
use security_framework::authorization::{Authorization, AuthorizationItemSetBuilder, Flags};
use nix::sys::socket::{socketpair, SockFlag, SockType, AddressFamily, recvmsg, MsgFlags, UnixAddr, RecvMsg};
use nix::unistd::close;
use nix::cmsg_space;
const DISK: &str = "/dev/rdisk3";
fn main() {
open_auth(DISK);
}
fn open_auth(path: &str) {
let rights = AuthorizationItemSetBuilder::new()
.add_right(format!("sys.openfile.readwrite.{}", path))
.unwrap()
.build();
let auth = Authorization::new(
Some(rights),
None,
Flags::INTERACTION_ALLOWED | Flags::EXTEND_RIGHTS | Flags::PREAUTHORIZE,
)
.unwrap();
let form = auth.make_external_form().unwrap();
let form_bytes: Vec<u8> = form.bytes.into_iter().map(|x| x as u8).collect();
let (srx, stx) = socketpair(
AddressFamily::Unix,
SockType::Stream,
None,
SockFlag::empty(),
)
.unwrap();
let mut cmd = Command::new("/usr/libexec/authopen")
.args(["-stdoutpipe", "-extauth", "-o", "02", path])
.stdin(Stdio::piped())
.stdout(stx)
.spawn()
.unwrap();
let mut stdin = cmd.stdin.take().unwrap();
stdin.write_all(&form_bytes).unwrap();
drop(stdin); // Закрываем stdin, чтобы отправить EOF
let mut buf = [0u8; 4];
let mut io_vec = [IoSliceMut::new(&mut buf)];
let mut cmsg = cmsg_space!(RawFd);
let msg: RecvMsg<'_, '_, UnixAddr> = recvmsg(
srx.as_raw_fd(),
&mut io_vec,
Some(&mut cmsg),
MsgFlags::empty(),
)
.unwrap();
println!("RMSG: {:?}", msg);
if let Some(cmsgs) = msg.cmsgs() {
for cmsg in cmsgs {
println!("CMSG: {:?}", cmsg);
}
}
let output = cmd.wait().unwrap();
println!("Raw output: {output:#?}");
close(srx).unwrap();
}
Шаг 4: Проверка контролируемых сообщений ScmRights
Обратите внимание на правильное извлечение и использование контролируемых сообщений ScmRights
. Обратите внимание на условия, которые нужны для успешной обработки этих сообщений.
Шаг 5: Отладка вывода
После внесенных изменений, попробуйте снова запустить ваш проект и внимательно проверьте вывод. Убедитесь, что вы получаете корректные данные из recvmsg
.
Заключение
Следуя вышеизложенным шагам, вы сможете исправить ошибки в вашем коде и успешно реализовать предварительное авторизованное открытие с использованием authopen
. Не забывайте проверять существование устройства и права доступа, а также правильно обрабатывать сокеты. Если проблемы сохраняются, тщательно проверяйте вывод отладки и уточняйте детали для дальнейшего анализа.