@@ -12,7 +12,7 @@ use crate::sync::Arc;
1212use crate :: sys:: handle:: Handle ;
1313use crate :: sys:: pal:: api:: { self , WinError , set_file_information_by_handle} ;
1414use crate :: sys:: pal:: { IoResult , fill_utf16_buf, to_u16s, truncate_utf16_at_nul} ;
15- use crate :: sys:: path:: maybe_verbatim;
15+ use crate :: sys:: path:: { WCStr , maybe_verbatim} ;
1616use crate :: sys:: time:: SystemTime ;
1717use crate :: sys:: { Align8 , c, cvt} ;
1818use crate :: sys_common:: { AsInner , FromInner , IntoInner } ;
@@ -298,10 +298,12 @@ impl OpenOptions {
298298impl File {
299299 pub fn open ( path : & Path , opts : & OpenOptions ) -> io:: Result < File > {
300300 let path = maybe_verbatim ( path) ?;
301+ // SAFETY: maybe_verbatim returns null-terminated strings
302+ let path = unsafe { WCStr :: from_wchars_with_null_unchecked ( & path) } ;
301303 Self :: open_native ( & path, opts)
302304 }
303305
304- fn open_native ( path : & [ u16 ] , opts : & OpenOptions ) -> io:: Result < File > {
306+ fn open_native ( path : & WCStr , opts : & OpenOptions ) -> io:: Result < File > {
305307 let creation = opts. get_creation_mode ( ) ?;
306308 let handle = unsafe {
307309 c:: CreateFileW (
@@ -1212,7 +1214,7 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> {
12121214 }
12131215}
12141216
1215- pub fn unlink ( path : & [ u16 ] ) -> io:: Result < ( ) > {
1217+ pub fn unlink ( path : & WCStr ) -> io:: Result < ( ) > {
12161218 if unsafe { c:: DeleteFileW ( path. as_ptr ( ) ) } == 0 {
12171219 let err = api:: get_last_error ( ) ;
12181220 // if `DeleteFileW` fails with ERROR_ACCESS_DENIED then try to remove
@@ -1235,7 +1237,7 @@ pub fn unlink(path: &[u16]) -> io::Result<()> {
12351237 }
12361238}
12371239
1238- pub fn rename ( old : & [ u16 ] , new : & [ u16 ] ) -> io:: Result < ( ) > {
1240+ pub fn rename ( old : & WCStr , new : & WCStr ) -> io:: Result < ( ) > {
12391241 if unsafe { c:: MoveFileExW ( old. as_ptr ( ) , new. as_ptr ( ) , c:: MOVEFILE_REPLACE_EXISTING ) } == 0 {
12401242 let err = api:: get_last_error ( ) ;
12411243 // if `MoveFileExW` fails with ERROR_ACCESS_DENIED then try to move
@@ -1249,7 +1251,8 @@ pub fn rename(old: &[u16], new: &[u16]) -> io::Result<()> {
12491251
12501252 // Calculate the layout of the `FILE_RENAME_INFO` we pass to `SetFileInformation`
12511253 // This is a dynamically sized struct so we need to get the position of the last field to calculate the actual size.
1252- let Ok ( new_len_without_nul_in_bytes) : Result < u32 , _ > = ( ( new. len ( ) - 1 ) * 2 ) . try_into ( )
1254+ let Ok ( new_len_without_nul_in_bytes) : Result < u32 , _ > =
1255+ ( ( new. count_bytes ( ) - 1 ) * 2 ) . try_into ( )
12531256 else {
12541257 return Err ( err) . io_result ( ) ;
12551258 } ;
@@ -1278,7 +1281,7 @@ pub fn rename(old: &[u16], new: &[u16]) -> io::Result<()> {
12781281
12791282 new. as_ptr ( ) . copy_to_nonoverlapping (
12801283 ( & raw mut ( * file_rename_info) . FileName ) . cast :: < u16 > ( ) ,
1281- new. len ( ) ,
1284+ new. count_bytes ( ) ,
12821285 ) ;
12831286 }
12841287
@@ -1305,12 +1308,12 @@ pub fn rename(old: &[u16], new: &[u16]) -> io::Result<()> {
13051308 Ok ( ( ) )
13061309}
13071310
1308- pub fn rmdir ( p : & [ u16 ] ) -> io:: Result < ( ) > {
1311+ pub fn rmdir ( p : & WCStr ) -> io:: Result < ( ) > {
13091312 cvt ( unsafe { c:: RemoveDirectoryW ( p. as_ptr ( ) ) } ) ?;
13101313 Ok ( ( ) )
13111314}
13121315
1313- pub fn remove_dir_all ( path : & [ u16 ] ) -> io:: Result < ( ) > {
1316+ pub fn remove_dir_all ( path : & WCStr ) -> io:: Result < ( ) > {
13141317 // Open a file or directory without following symlinks.
13151318 let mut opts = OpenOptions :: new ( ) ;
13161319 opts. access_mode ( c:: FILE_LIST_DIRECTORY ) ;
@@ -1328,7 +1331,7 @@ pub fn remove_dir_all(path: &[u16]) -> io::Result<()> {
13281331 remove_dir_all_iterative ( file) . io_result ( )
13291332}
13301333
1331- pub fn readlink ( path : & [ u16 ] ) -> io:: Result < PathBuf > {
1334+ pub fn readlink ( path : & WCStr ) -> io:: Result < PathBuf > {
13321335 // Open the link with no access mode, instead of generic read.
13331336 // By default FILE_LIST_DIRECTORY is denied for the junction "C:\Documents and Settings", so
13341337 // this is needed for a common case.
@@ -1373,17 +1376,17 @@ pub fn symlink_inner(original: &Path, link: &Path, dir: bool) -> io::Result<()>
13731376}
13741377
13751378#[ cfg( not( target_vendor = "uwp" ) ) ]
1376- pub fn link ( original : & [ u16 ] , link : & [ u16 ] ) -> io:: Result < ( ) > {
1379+ pub fn link ( original : & WCStr , link : & WCStr ) -> io:: Result < ( ) > {
13771380 cvt ( unsafe { c:: CreateHardLinkW ( link. as_ptr ( ) , original. as_ptr ( ) , ptr:: null_mut ( ) ) } ) ?;
13781381 Ok ( ( ) )
13791382}
13801383
13811384#[ cfg( target_vendor = "uwp" ) ]
1382- pub fn link ( _original : & [ u16 ] , _link : & [ u16 ] ) -> io:: Result < ( ) > {
1385+ pub fn link ( _original : & WCStr , _link : & WCStr ) -> io:: Result < ( ) > {
13831386 return Err ( io:: const_error!( io:: ErrorKind :: Unsupported , "hard link are not supported on UWP" ) ) ;
13841387}
13851388
1386- pub fn stat ( path : & [ u16 ] ) -> io:: Result < FileAttr > {
1389+ pub fn stat ( path : & WCStr ) -> io:: Result < FileAttr > {
13871390 match metadata ( path, ReparsePoint :: Follow ) {
13881391 Err ( err) if err. raw_os_error ( ) == Some ( c:: ERROR_CANT_ACCESS_FILE as i32 ) => {
13891392 if let Ok ( attrs) = lstat ( path) {
@@ -1397,7 +1400,7 @@ pub fn stat(path: &[u16]) -> io::Result<FileAttr> {
13971400 }
13981401}
13991402
1400- pub fn lstat ( path : & [ u16 ] ) -> io:: Result < FileAttr > {
1403+ pub fn lstat ( path : & WCStr ) -> io:: Result < FileAttr > {
14011404 metadata ( path, ReparsePoint :: Open )
14021405}
14031406
@@ -1413,7 +1416,7 @@ impl ReparsePoint {
14131416 }
14141417}
14151418
1416- fn metadata ( path : & [ u16 ] , reparse : ReparsePoint ) -> io:: Result < FileAttr > {
1419+ fn metadata ( path : & WCStr , reparse : ReparsePoint ) -> io:: Result < FileAttr > {
14171420 let mut opts = OpenOptions :: new ( ) ;
14181421 // No read or write permissions are necessary
14191422 opts. access_mode ( 0 ) ;
@@ -1473,7 +1476,7 @@ fn metadata(path: &[u16], reparse: ReparsePoint) -> io::Result<FileAttr> {
14731476 }
14741477}
14751478
1476- pub fn set_perm ( p : & [ u16 ] , perm : FilePermissions ) -> io:: Result < ( ) > {
1479+ pub fn set_perm ( p : & WCStr , perm : FilePermissions ) -> io:: Result < ( ) > {
14771480 unsafe {
14781481 cvt ( c:: SetFileAttributesW ( p. as_ptr ( ) , perm. attrs ) ) ?;
14791482 Ok ( ( ) )
@@ -1489,7 +1492,7 @@ fn get_path(f: &File) -> io::Result<PathBuf> {
14891492 )
14901493}
14911494
1492- pub fn canonicalize ( p : & [ u16 ] ) -> io:: Result < PathBuf > {
1495+ pub fn canonicalize ( p : & WCStr ) -> io:: Result < PathBuf > {
14931496 let mut opts = OpenOptions :: new ( ) ;
14941497 // No read or write permissions are necessary
14951498 opts. access_mode ( 0 ) ;
@@ -1499,7 +1502,7 @@ pub fn canonicalize(p: &[u16]) -> io::Result<PathBuf> {
14991502 get_path ( & f)
15001503}
15011504
1502- pub fn copy ( from : & [ u16 ] , to : & [ u16 ] ) -> io:: Result < u64 > {
1505+ pub fn copy ( from : & WCStr , to : & WCStr ) -> io:: Result < u64 > {
15031506 unsafe extern "system" fn callback (
15041507 _TotalFileSize : i64 ,
15051508 _TotalBytesTransferred : i64 ,
@@ -1612,7 +1615,7 @@ pub fn junction_point(original: &Path, link: &Path) -> io::Result<()> {
16121615}
16131616
16141617// Try to see if a file exists but, unlike `exists`, report I/O errors.
1615- pub fn exists ( path : & [ u16 ] ) -> io:: Result < bool > {
1618+ pub fn exists ( path : & WCStr ) -> io:: Result < bool > {
16161619 // Open the file to ensure any symlinks are followed to their target.
16171620 let mut opts = OpenOptions :: new ( ) ;
16181621 // No read, write, etc access rights are needed.
0 commit comments