@@ -298,19 +298,48 @@ impl Error for VarError {
298
298
}
299
299
}
300
300
301
+ #[ unstable( feature = "unsafe_env" , issue = "none" ) ]
301
302
/// Sets the environment variable `key` to the value `value` for the currently running
302
303
/// process.
303
304
///
304
- /// Note that while concurrent access to environment variables is safe in Rust,
305
- /// some platforms only expose inherently unsafe non-threadsafe APIs for
306
- /// inspecting the environment. As a result, extra care needs to be taken when
307
- /// auditing calls to unsafe external FFI functions to ensure that any external
308
- /// environment accesses are properly synchronized with accesses in Rust.
305
+ /// # Safety
309
306
///
310
- /// Discussion of this unsafety on Unix may be found in:
307
+ /// This function must not be called in the presence of concurrent threads that
308
+ /// may simultaneously read or write the environment. Also, it's not allowed
309
+ /// to use this function in functions marked with `#[test]` attribute because
310
+ /// test harness uses threads internally.
311
311
///
312
- /// - [Austin Group Bugzilla](https://austingroupbugs.net/view.php?id=188)
313
- /// - [GNU C library Bugzilla](https://sourceware.org/bugzilla/show_bug.cgi?id=15607#c2)
312
+ /// # Panics
313
+ ///
314
+ /// This function may panic if `key` is empty, contains an ASCII equals sign `'='`
315
+ /// or the NUL character `'\0'`, or when `value` contains the NUL character.
316
+ ///
317
+ /// # Examples
318
+ ///
319
+ /// ```
320
+ /// #![feature(unsafe_env)]
321
+ ///
322
+ /// use std::env;
323
+ ///
324
+ /// let key = "KEY";
325
+ /// unsafe {
326
+ /// env::set(key, "VALUE");
327
+ /// }
328
+ /// assert_eq!(env::var(key), Ok("VALUE".to_string()));
329
+ /// ```
330
+ pub unsafe fn set < K : AsRef < OsStr > , V : AsRef < OsStr > > ( key : K , value : V ) {
331
+ _set_var ( key. as_ref ( ) , value. as_ref ( ) , |k, v| os_imp:: setenv ( k, v) )
332
+ }
333
+
334
+ /// Sets the environment variable `key` to the value `value` for the currently running
335
+ /// process.
336
+ ///
337
+ /// # Safety
338
+ ///
339
+ /// This function must not be called in the presence of concurrent threads that
340
+ /// may simultaneously read or write the environment. Also, it's not allowed
341
+ /// to use this function in functions marked with `#[test]` attribute because
342
+ /// test harness uses threads internally.
314
343
///
315
344
/// # Panics
316
345
///
@@ -328,27 +357,59 @@ impl Error for VarError {
328
357
/// ```
329
358
#[ stable( feature = "env" , since = "1.0.0" ) ]
330
359
pub fn set_var < K : AsRef < OsStr > , V : AsRef < OsStr > > ( key : K , value : V ) {
331
- _set_var ( key. as_ref ( ) , value. as_ref ( ) )
360
+ _set_var ( key. as_ref ( ) , value. as_ref ( ) , |k , v| unsafe { os_imp :: setenv_locking ( k , v ) } )
332
361
}
333
362
334
- fn _set_var ( key : & OsStr , value : & OsStr ) {
335
- os_imp :: setenv ( key, value) . unwrap_or_else ( |e| {
363
+ fn _set_var < F : Fn ( & OsStr , & OsStr ) -> io :: Result < ( ) > > ( key : & OsStr , value : & OsStr , f : F ) {
364
+ f ( key, value) . unwrap_or_else ( |e| {
336
365
panic ! ( "failed to set environment variable `{:?}` to `{:?}`: {}" , key, value, e)
337
366
} )
338
367
}
339
368
369
+ #[ unstable( feature = "unsafe_env" , issue = "none" ) ]
340
370
/// Removes an environment variable from the environment of the currently running process.
341
371
///
342
- /// Note that while concurrent access to environment variables is safe in Rust,
343
- /// some platforms only expose inherently unsafe non-threadsafe APIs for
344
- /// inspecting the environment. As a result extra care needs to be taken when
345
- /// auditing calls to unsafe external FFI functions to ensure that any external
346
- /// environment accesses are properly synchronized with accesses in Rust.
372
+ /// # Safety
373
+ ///
374
+ /// This function must not be called in the presence of concurrent threads that
375
+ /// may simultaneously read or write the environment. Also, it's not allowed
376
+ /// to use this function in functions marked with `#[test]` attribute because
377
+ /// test harness uses threads internally.
378
+ ///
379
+ /// # Panics
380
+ ///
381
+ /// This function may panic if `key` is empty, contains an ASCII equals sign
382
+ /// `'='` or the NUL character `'\0'`, or when the value contains the NUL
383
+ /// character.
384
+ ///
385
+ /// # Examples
386
+ ///
387
+ /// ```
388
+ /// #![feature(unsafe_env)]
389
+ ///
390
+ /// use std::env;
391
+ ///
392
+ /// let key = "KEY";
393
+ /// env::set_var(key, "VALUE");
394
+ /// assert_eq!(env::var(key), Ok("VALUE".to_string()));
395
+ ///
396
+ /// unsafe {
397
+ /// env::remove(key);
398
+ /// }
399
+ /// assert!(env::var(key).is_err());
400
+ /// ```
401
+ pub unsafe fn remove < K : AsRef < OsStr > > ( key : K ) {
402
+ _remove_var ( key. as_ref ( ) , |n| os_imp:: unsetenv ( n) )
403
+ }
404
+
405
+ /// Removes an environment variable from the environment of the currently running process.
347
406
///
348
- /// Discussion of this unsafety on Unix may be found in:
407
+ /// # Safety
349
408
///
350
- /// - [Austin Group Bugzilla](https://austingroupbugs.net/view.php?id=188)
351
- /// - [GNU C library Bugzilla](https://sourceware.org/bugzilla/show_bug.cgi?id=15607#c2)
409
+ /// This function must not be called in the presence of concurrent threads that
410
+ /// may simultaneously read or write the environment. Also, it's not allowed
411
+ /// to use this function in functions marked with `#[test]` attribute because
412
+ /// test harness uses threads internally.
352
413
///
353
414
/// # Panics
354
415
///
@@ -370,12 +431,11 @@ fn _set_var(key: &OsStr, value: &OsStr) {
370
431
/// ```
371
432
#[ stable( feature = "env" , since = "1.0.0" ) ]
372
433
pub fn remove_var < K : AsRef < OsStr > > ( key : K ) {
373
- _remove_var ( key. as_ref ( ) )
434
+ _remove_var ( key. as_ref ( ) , |n| unsafe { os_imp :: unsetenv_locking ( n ) } )
374
435
}
375
436
376
- fn _remove_var ( key : & OsStr ) {
377
- os_imp:: unsetenv ( key)
378
- . unwrap_or_else ( |e| panic ! ( "failed to remove environment variable `{:?}`: {}" , key, e) )
437
+ fn _remove_var < F : Fn ( & OsStr ) -> io:: Result < ( ) > > ( key : & OsStr , f : F ) {
438
+ f ( key) . unwrap_or_else ( |e| panic ! ( "failed to remove environment variable `{:?}`: {}" , key, e) )
379
439
}
380
440
381
441
/// An iterator that splits an environment variable into paths according to
0 commit comments