@@ -12,7 +12,7 @@ use crate::sync::Arc;
12
12
use crate :: sys:: handle:: Handle ;
13
13
use crate :: sys:: pal:: api:: { self , WinError , set_file_information_by_handle} ;
14
14
use 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} ;
16
16
use crate :: sys:: time:: SystemTime ;
17
17
use crate :: sys:: { Align8 , c, cvt} ;
18
18
use crate :: sys_common:: { AsInner , FromInner , IntoInner } ;
@@ -298,10 +298,12 @@ impl OpenOptions {
298
298
impl File {
299
299
pub fn open ( path : & Path , opts : & OpenOptions ) -> io:: Result < File > {
300
300
let path = maybe_verbatim ( path) ?;
301
+ // SAFETY: maybe_verbatim returns null-terminated strings
302
+ let path = unsafe { WCStr :: new_unchecked ( & path) } ;
301
303
Self :: open_native ( & path, opts)
302
304
}
303
305
304
- fn open_native ( path : & [ u16 ] , opts : & OpenOptions ) -> io:: Result < File > {
306
+ fn open_native ( path : & WCStr , opts : & OpenOptions ) -> io:: Result < File > {
305
307
let creation = opts. get_creation_mode ( ) ?;
306
308
let handle = unsafe {
307
309
c:: CreateFileW (
@@ -1212,7 +1214,7 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> {
1212
1214
}
1213
1215
}
1214
1216
1215
- pub fn unlink ( path : & [ u16 ] ) -> io:: Result < ( ) > {
1217
+ pub fn unlink ( path : & WCStr ) -> io:: Result < ( ) > {
1216
1218
if unsafe { c:: DeleteFileW ( path. as_ptr ( ) ) } == 0 {
1217
1219
let err = api:: get_last_error ( ) ;
1218
1220
// if `DeleteFileW` fails with ERROR_ACCESS_DENIED then try to remove
@@ -1235,7 +1237,7 @@ pub fn unlink(path: &[u16]) -> io::Result<()> {
1235
1237
}
1236
1238
}
1237
1239
1238
- pub fn rename ( old : & [ u16 ] , new : & [ u16 ] ) -> io:: Result < ( ) > {
1240
+ pub fn rename ( old : & WCStr , new : & WCStr ) -> io:: Result < ( ) > {
1239
1241
if unsafe { c:: MoveFileExW ( old. as_ptr ( ) , new. as_ptr ( ) , c:: MOVEFILE_REPLACE_EXISTING ) } == 0 {
1240
1242
let err = api:: get_last_error ( ) ;
1241
1243
// if `MoveFileExW` fails with ERROR_ACCESS_DENIED then try to move
@@ -1305,12 +1307,12 @@ pub fn rename(old: &[u16], new: &[u16]) -> io::Result<()> {
1305
1307
Ok ( ( ) )
1306
1308
}
1307
1309
1308
- pub fn rmdir ( p : & [ u16 ] ) -> io:: Result < ( ) > {
1310
+ pub fn rmdir ( p : & WCStr ) -> io:: Result < ( ) > {
1309
1311
cvt ( unsafe { c:: RemoveDirectoryW ( p. as_ptr ( ) ) } ) ?;
1310
1312
Ok ( ( ) )
1311
1313
}
1312
1314
1313
- pub fn remove_dir_all ( path : & [ u16 ] ) -> io:: Result < ( ) > {
1315
+ pub fn remove_dir_all ( path : & WCStr ) -> io:: Result < ( ) > {
1314
1316
// Open a file or directory without following symlinks.
1315
1317
let mut opts = OpenOptions :: new ( ) ;
1316
1318
opts. access_mode ( c:: FILE_LIST_DIRECTORY ) ;
@@ -1328,7 +1330,7 @@ pub fn remove_dir_all(path: &[u16]) -> io::Result<()> {
1328
1330
remove_dir_all_iterative ( file) . io_result ( )
1329
1331
}
1330
1332
1331
- pub fn readlink ( path : & [ u16 ] ) -> io:: Result < PathBuf > {
1333
+ pub fn readlink ( path : & WCStr ) -> io:: Result < PathBuf > {
1332
1334
// Open the link with no access mode, instead of generic read.
1333
1335
// By default FILE_LIST_DIRECTORY is denied for the junction "C:\Documents and Settings", so
1334
1336
// this is needed for a common case.
@@ -1373,17 +1375,17 @@ pub fn symlink_inner(original: &Path, link: &Path, dir: bool) -> io::Result<()>
1373
1375
}
1374
1376
1375
1377
#[ cfg( not( target_vendor = "uwp" ) ) ]
1376
- pub fn link ( original : & [ u16 ] , link : & [ u16 ] ) -> io:: Result < ( ) > {
1378
+ pub fn link ( original : & WCStr , link : & WCStr ) -> io:: Result < ( ) > {
1377
1379
cvt ( unsafe { c:: CreateHardLinkW ( link. as_ptr ( ) , original. as_ptr ( ) , ptr:: null_mut ( ) ) } ) ?;
1378
1380
Ok ( ( ) )
1379
1381
}
1380
1382
1381
1383
#[ cfg( target_vendor = "uwp" ) ]
1382
- pub fn link ( _original : & [ u16 ] , _link : & [ u16 ] ) -> io:: Result < ( ) > {
1384
+ pub fn link ( _original : & WCStr , _link : & WCStr ) -> io:: Result < ( ) > {
1383
1385
return Err ( io:: const_error!( io:: ErrorKind :: Unsupported , "hard link are not supported on UWP" ) ) ;
1384
1386
}
1385
1387
1386
- pub fn stat ( path : & [ u16 ] ) -> io:: Result < FileAttr > {
1388
+ pub fn stat ( path : & WCStr ) -> io:: Result < FileAttr > {
1387
1389
match metadata ( path, ReparsePoint :: Follow ) {
1388
1390
Err ( err) if err. raw_os_error ( ) == Some ( c:: ERROR_CANT_ACCESS_FILE as i32 ) => {
1389
1391
if let Ok ( attrs) = lstat ( path) {
@@ -1397,7 +1399,7 @@ pub fn stat(path: &[u16]) -> io::Result<FileAttr> {
1397
1399
}
1398
1400
}
1399
1401
1400
- pub fn lstat ( path : & [ u16 ] ) -> io:: Result < FileAttr > {
1402
+ pub fn lstat ( path : & WCStr ) -> io:: Result < FileAttr > {
1401
1403
metadata ( path, ReparsePoint :: Open )
1402
1404
}
1403
1405
@@ -1413,7 +1415,7 @@ impl ReparsePoint {
1413
1415
}
1414
1416
}
1415
1417
1416
- fn metadata ( path : & [ u16 ] , reparse : ReparsePoint ) -> io:: Result < FileAttr > {
1418
+ fn metadata ( path : & WCStr , reparse : ReparsePoint ) -> io:: Result < FileAttr > {
1417
1419
let mut opts = OpenOptions :: new ( ) ;
1418
1420
// No read or write permissions are necessary
1419
1421
opts. access_mode ( 0 ) ;
@@ -1473,7 +1475,7 @@ fn metadata(path: &[u16], reparse: ReparsePoint) -> io::Result<FileAttr> {
1473
1475
}
1474
1476
}
1475
1477
1476
- pub fn set_perm ( p : & [ u16 ] , perm : FilePermissions ) -> io:: Result < ( ) > {
1478
+ pub fn set_perm ( p : & WCStr , perm : FilePermissions ) -> io:: Result < ( ) > {
1477
1479
unsafe {
1478
1480
cvt ( c:: SetFileAttributesW ( p. as_ptr ( ) , perm. attrs ) ) ?;
1479
1481
Ok ( ( ) )
@@ -1489,7 +1491,7 @@ fn get_path(f: &File) -> io::Result<PathBuf> {
1489
1491
)
1490
1492
}
1491
1493
1492
- pub fn canonicalize ( p : & [ u16 ] ) -> io:: Result < PathBuf > {
1494
+ pub fn canonicalize ( p : & WCStr ) -> io:: Result < PathBuf > {
1493
1495
let mut opts = OpenOptions :: new ( ) ;
1494
1496
// No read or write permissions are necessary
1495
1497
opts. access_mode ( 0 ) ;
@@ -1499,7 +1501,7 @@ pub fn canonicalize(p: &[u16]) -> io::Result<PathBuf> {
1499
1501
get_path ( & f)
1500
1502
}
1501
1503
1502
- pub fn copy ( from : & [ u16 ] , to : & [ u16 ] ) -> io:: Result < u64 > {
1504
+ pub fn copy ( from : & WCStr , to : & WCStr ) -> io:: Result < u64 > {
1503
1505
unsafe extern "system" fn callback (
1504
1506
_TotalFileSize : i64 ,
1505
1507
_TotalBytesTransferred : i64 ,
@@ -1612,7 +1614,7 @@ pub fn junction_point(original: &Path, link: &Path) -> io::Result<()> {
1612
1614
}
1613
1615
1614
1616
// Try to see if a file exists but, unlike `exists`, report I/O errors.
1615
- pub fn exists ( path : & [ u16 ] ) -> io:: Result < bool > {
1617
+ pub fn exists ( path : & WCStr ) -> io:: Result < bool > {
1616
1618
// Open the file to ensure any symlinks are followed to their target.
1617
1619
let mut opts = OpenOptions :: new ( ) ;
1618
1620
// No read, write, etc access rights are needed.
0 commit comments