std: uefi: Add basic Env variables · qinheping/verify-rust-std@f973e62 (original) (raw)

`@@ -192,44 +192,58 @@ pub fn current_exe() -> io::Result {

`

192

192

` helpers::device_path_to_text(protocol).map(PathBuf::from)

`

193

193

`}

`

194

194

``

195

``

`-

pub struct Env(!);

`

``

195

`+

pub struct EnvStrDebug<'a> {

`

``

196

`+

iter: &'a [(OsString, OsString)],

`

``

197

`+

}

`

``

198

+

``

199

`+

impl fmt::Debug for EnvStrDebug<'_> {

`

``

200

`+

fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {

`

``

201

`+

let mut list = f.debug_list();

`

``

202

`+

for (a, b) in self.iter {

`

``

203

`+

list.entry(&(a.to_str().unwrap(), b.to_str().unwrap()));

`

``

204

`+

}

`

``

205

`+

list.finish()

`

``

206

`+

}

`

``

207

`+

}

`

``

208

+

``

209

`+

pub struct Env(crate::vec::IntoIter<(OsString, OsString)>);

`

196

210

``

197

211

`impl Env {

`

198

212

`// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when ::fmt matches ::fmt.

`

199

213

`pub fn str_debug(&self) -> impl fmt::Debug + '_ {

`

200

``

`-

let Self(inner) = self;

`

201

``

`-

match *inner {}

`

``

214

`+

EnvStrDebug { iter: self.0.as_slice() }

`

202

215

`}

`

203

216

`}

`

204

217

``

205

218

`impl Iterator for Env {

`

206

219

`type Item = (OsString, OsString);

`

``

220

+

207

221

`fn next(&mut self) -> Option<(OsString, OsString)> {

`

208

``

`-

self.0

`

``

222

`+

self.0.next()

`

209

223

`}

`

210

224

`}

`

211

225

``

212

226

`impl fmt::Debug for Env {

`

213

``

`-

fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {

`

214

``

`-

let Self(inner) = self;

`

215

``

`-

match *inner {}

`

``

227

`+

fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {

`

``

228

`+

self.0.fmt(f)

`

216

229

`}

`

217

230

`}

`

218

231

``

219

232

`pub fn env() -> Env {

`

220

``

`-

panic!("not supported on this platform")

`

``

233

`+

let env = uefi_env::get_all().expect("not supported on this platform");

`

``

234

`+

Env(env.into_iter())

`

221

235

`}

`

222

236

``

223

``

`-

pub fn getenv(_: &OsStr) -> Option {

`

224

``

`-

None

`

``

237

`+

pub fn getenv(key: &OsStr) -> Option {

`

``

238

`+

uefi_env::get(key)

`

225

239

`}

`

226

240

``

227

``

`-

pub unsafe fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> {

`

228

``

`-

Err(io::const_io_error!(io::ErrorKind::Unsupported, "cannot set env vars on this platform"))

`

``

241

`+

pub unsafe fn setenv(key: &OsStr, val: &OsStr) -> io::Result<()> {

`

``

242

`+

uefi_env::set(key, val)

`

229

243

`}

`

230

244

``

231

``

`-

pub unsafe fn unsetenv(_: &OsStr) -> io::Result<()> {

`

232

``

`-

Err(io::const_io_error!(io::ErrorKind::Unsupported, "cannot unset env vars on this platform"))

`

``

245

`+

pub unsafe fn unsetenv(key: &OsStr) -> io::Result<()> {

`

``

246

`+

uefi_env::unset(key)

`

233

247

`}

`

234

248

``

235

249

`pub fn temp_dir() -> PathBuf {

`

`@@ -294,3 +308,85 @@ mod uefi_shell {

`

294

308

`None

`

295

309

`}

`

296

310

`}

`

``

311

+

``

312

`+

mod uefi_env {

`

``

313

`+

use crate::ffi::{OsStr, OsString};

`

``

314

`+

use crate::io;

`

``

315

`+

use crate::os::uefi::ffi::OsStringExt;

`

``

316

`+

use crate::ptr::NonNull;

`

``

317

`+

use crate::sys::{helpers, unsupported_err};

`

``

318

+

``

319

`+

pub(crate) fn get(key: &OsStr) -> Option {

`

``

320

`+

let shell = helpers::open_shell()?;

`

``

321

`+

let mut key_ptr = helpers::os_string_to_raw(key)?;

`

``

322

`+

unsafe { get_raw(shell, key_ptr.as_mut_ptr()) }

`

``

323

`+

}

`

``

324

+

``

325

`+

pub(crate) fn set(key: &OsStr, val: &OsStr) -> io::Result<()> {

`

``

326

`+

let mut key_ptr = helpers::os_string_to_raw(key)

`

``

327

`+

.ok_or(io::const_io_error!(io::ErrorKind::InvalidInput, "Invalid Key"))?;

`

``

328

`+

let mut val_ptr = helpers::os_string_to_raw(val)

`

``

329

`+

.ok_or(io::const_io_error!(io::ErrorKind::InvalidInput, "Invalid Value"))?;

`

``

330

`+

unsafe { set_raw(key_ptr.as_mut_ptr(), val_ptr.as_mut_ptr()) }

`

``

331

`+

}

`

``

332

+

``

333

`+

pub(crate) fn unset(key: &OsStr) -> io::Result<()> {

`

``

334

`+

let mut key_ptr = helpers::os_string_to_raw(key)

`

``

335

`+

.ok_or(io::const_io_error!(io::ErrorKind::InvalidInput, "Invalid Key"))?;

`

``

336

`+

unsafe { set_raw(key_ptr.as_mut_ptr(), crate::ptr::null_mut()) }

`

``

337

`+

}

`

``

338

+

``

339

`+

pub(crate) fn get_all() -> io::Result<Vec<(OsString, OsString)>> {

`

``

340

`+

let shell = helpers::open_shell().ok_or(unsupported_err())?;

`

``

341

+

``

342

`+

let mut vars = Vec::new();

`

``

343

`+

let val = unsafe { ((*shell.as_ptr()).get_env)(crate::ptr::null_mut()) };

`

``

344

+

``

345

`+

if val.is_null() {

`

``

346

`+

return Ok(vars);

`

``

347

`+

}

`

``

348

+

``

349

`+

let mut start = 0;

`

``

350

+

``

351

`+

// UEFI Shell returns all keys seperated by NULL.

`

``

352

`+

// End of string is denoted by two NULLs

`

``

353

`+

for i in 0.. {

`

``

354

`+

if unsafe { *val.add(i) } == 0 {

`

``

355

`+

// Two NULL signal end of string

`

``

356

`+

if i == start {

`

``

357

`+

break;

`

``

358

`+

}

`

``

359

+

``

360

`+

let key = OsString::from_wide(unsafe {

`

``

361

`+

crate::slice::from_raw_parts(val.add(start), i - start)

`

``

362

`+

});

`

``

363

`+

// SAFETY: val.add(start) is always NULL terminated

`

``

364

`+

let val = unsafe { get_raw(shell, val.add(start)) }

`

``

365

`+

.ok_or(io::const_io_error!(io::ErrorKind::InvalidInput, "Invalid Value"))?;

`

``

366

+

``

367

`+

vars.push((key, val));

`

``

368

`+

start = i + 1;

`

``

369

`+

}

`

``

370

`+

}

`

``

371

+

``

372

`+

Ok(vars)

`

``

373

`+

}

`

``

374

+

``

375

`+

unsafe fn get_raw(

`

``

376

`+

shell: NonNull<r_efi::efi::protocols:🐚:Protocol>,

`

``

377

`+

key_ptr: *mut r_efi::efi::Char16,

`

``

378

`+

) -> Option {

`

``

379

`+

let val = unsafe { ((*shell.as_ptr()).get_env)(key_ptr) };

`

``

380

`+

helpers::os_string_from_raw(val)

`

``

381

`+

}

`

``

382

+

``

383

`+

unsafe fn set_raw(

`

``

384

`+

key_ptr: *mut r_efi::efi::Char16,

`

``

385

`+

val_ptr: *mut r_efi::efi::Char16,

`

``

386

`+

) -> io::Result<()> {

`

``

387

`+

let shell = helpers::open_shell().ok_or(unsupported_err())?;

`

``

388

`+

let r =

`

``

389

`+

unsafe { ((*shell.as_ptr()).set_env)(key_ptr, val_ptr, r_efi::efi::Boolean::FALSE) };

`

``

390

`+

if r.is_error() { Err(io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) }

`

``

391

`+

}

`

``

392

`+

}

`