@@ -6,7 +6,6 @@ use crate::common::{
6
6
} ;
7
7
use crate :: env:: { EnvVar , EnvVarFlags , VarTable } ;
8
8
use crate :: fallback:: fish_mkstemp_cloexec;
9
- use crate :: fds:: AutoCloseFd ;
10
9
use crate :: fds:: { open_cloexec, wopen_cloexec} ;
11
10
use crate :: flog:: { FLOG , FLOGF } ;
12
11
use crate :: path:: path_get_config;
@@ -493,39 +492,41 @@ impl EnvUniversal {
493
492
res_fd
494
493
}
495
494
496
- fn open_temporary_file ( & mut self , directory : & wstr , out_path : & mut WString ) -> AutoCloseFd {
495
+ fn open_temporary_file ( & mut self , directory : & wstr , out_path : & mut WString ) -> OwnedFd {
497
496
// Create and open a temporary file for writing within the given directory. Try to create a
498
497
// temporary file, up to 10 times. We don't use mkstemps because we want to open it CLO_EXEC.
499
498
// This should almost always succeed on the first try.
500
499
assert ! ( !string_suffixes_string( L !( "/" ) , directory) ) ;
501
500
502
- let mut saved_errno = Errno ( 0 ) ;
501
+ let mut attempt = 0 ;
503
502
let tmp_name_template = directory. to_owned ( ) + L ! ( "/fishd.tmp.XXXXXX" ) ;
504
- let mut result = AutoCloseFd :: empty ( ) ;
505
- let mut narrow_str = CString :: default ( ) ;
506
- for _attempt in 0 ..10 {
507
- if result. is_valid ( ) {
508
- break ;
503
+ let result = loop {
504
+ attempt += 1 ;
505
+ let result = fish_mkstemp_cloexec ( wcs2zstring ( & tmp_name_template) ) ;
506
+ match ( result, attempt) {
507
+ ( Ok ( r) , _) => break r,
508
+ ( Err ( e) , 10 ) => {
509
+ FLOG ! (
510
+ error,
511
+ // We previously used to log a copy of the buffer we expected mk(o)stemp to
512
+ // update with the new path, but mkstemp(3) says the contents of the buffer
513
+ // are undefined in case of EEXIST, but left unchanged in case of EINVAL. So
514
+ // just log the original template we pass in to the function instead.
515
+ wgettext_fmt!(
516
+ "Unable to create temporary file '%ls': %s" ,
517
+ & tmp_name_template,
518
+ e. to_string( )
519
+ )
520
+ ) ;
521
+ }
522
+ _ => continue ,
509
523
}
510
- let ( fd, tmp_name) = fish_mkstemp_cloexec ( wcs2zstring ( & tmp_name_template) ) ;
511
- result. reset ( fd) ;
512
- narrow_str = tmp_name;
513
- saved_errno = errno ( ) ;
514
- }
515
- * out_path = str2wcstring ( narrow_str. as_bytes ( ) ) ;
524
+ } ;
516
525
517
- if !result. is_valid ( ) {
518
- FLOG ! (
519
- error,
520
- wgettext_fmt!(
521
- "Unable to open temporary file '%ls': %s" ,
522
- out_path,
523
- saved_errno. to_string( )
524
- )
525
- ) ;
526
- }
527
- result
526
+ * out_path = str2wcstring ( result. 1 . as_bytes ( ) ) ;
527
+ result. 0
528
528
}
529
+
529
530
/// Writes our state to the fd. path is provided only for error reporting.
530
531
fn write_to_fd ( & mut self , fd : RawFd , path : & wstr ) -> bool {
531
532
assert ! ( fd >= 0 ) ;
@@ -753,19 +754,11 @@ impl EnvUniversal {
753
754
754
755
// Open adjacent temporary file.
755
756
let private_fd = self . open_temporary_file ( directory, & mut private_file_path) ;
756
- let mut success = private_fd. is_valid ( ) ;
757
-
758
- if !success {
759
- FLOG ! ( uvar_file, "universal log open_temporary_file() failed" ) ;
760
- }
761
757
762
758
// Write to it.
763
- if success {
764
- assert ! ( private_fd. is_valid( ) ) ;
765
- success = self . write_to_fd ( private_fd. fd ( ) , & private_file_path) ;
766
- if !success {
767
- FLOG ! ( uvar_file, "universal log write_to_fd() failed" ) ;
768
- }
759
+ let mut success = self . write_to_fd ( private_fd. as_raw_fd ( ) , & private_file_path) ;
760
+ if !success {
761
+ FLOG ! ( uvar_file, "universal log write_to_fd() failed" ) ;
769
762
}
770
763
771
764
if success {
@@ -774,12 +767,12 @@ impl EnvUniversal {
774
767
// Ensure we maintain ownership and permissions (#2176).
775
768
// let mut sbuf : libc::stat = MaybeUninit::uninit();
776
769
if let Ok ( md) = wstat ( & real_path) {
777
- if unsafe { libc:: fchown ( private_fd. fd ( ) , md. uid ( ) , md. gid ( ) ) } == -1 {
770
+ if unsafe { libc:: fchown ( private_fd. as_raw_fd ( ) , md. uid ( ) , md. gid ( ) ) } == -1 {
778
771
FLOG ! ( uvar_file, "universal log fchown() failed" ) ;
779
772
}
780
773
#[ allow( clippy:: useless_conversion) ]
781
774
let mode: libc:: mode_t = md. mode ( ) . try_into ( ) . unwrap ( ) ;
782
- if unsafe { libc:: fchmod ( private_fd. fd ( ) , mode) } == -1 {
775
+ if unsafe { libc:: fchmod ( private_fd. as_raw_fd ( ) , mode) } == -1 {
783
776
FLOG ! ( uvar_file, "universal log fchmod() failed" ) ;
784
777
}
785
778
}
@@ -802,7 +795,7 @@ impl EnvUniversal {
802
795
times[ 0 ] . tv_nsec = libc:: UTIME_OMIT ; // don't change ctime
803
796
if unsafe { libc:: clock_gettime ( libc:: CLOCK_REALTIME , & mut times[ 1 ] ) } != 0 {
804
797
unsafe {
805
- libc:: futimens ( private_fd. fd ( ) , & times[ 0 ] ) ;
798
+ libc:: futimens ( private_fd. as_raw_fd ( ) , & times[ 0 ] ) ;
806
799
}
807
800
}
808
801
}
0 commit comments