@@ -11,6 +11,7 @@ use crate::ptr;
1111use crate :: slice;
1212use crate :: sync:: Arc ;
1313use crate :: sys:: handle:: Handle ;
14+ use crate :: sys:: path:: NativePath ;
1415use crate :: sys:: time:: SystemTime ;
1516use crate :: sys:: { c, cvt, Align8 } ;
1617use crate :: sys_common:: { AsInner , FromInner , IntoInner } ;
@@ -19,6 +20,60 @@ use crate::thread;
1920use super :: { api, to_u16s, IoResult } ;
2021use crate :: sys:: path:: maybe_verbatim;
2122
23+ /// The crate-public interface
24+ pub ( crate ) mod fs_imp {
25+ use crate :: io;
26+ use crate :: path:: AsPath ;
27+ use crate :: path:: PathBuf ;
28+ use crate :: sys:: fs;
29+ pub ( crate ) use crate :: sys:: fs:: {
30+ DirBuilder , DirEntry , File , FileAttr , FilePermissions , FileTimes , FileType , OpenOptions ,
31+ ReadDir ,
32+ } ;
33+ pub ( crate ) fn remove_file < P : AsPath > ( path : P ) -> io:: Result < ( ) > {
34+ path. with_path ( fs:: unlink)
35+ }
36+ pub ( crate ) fn symlink_metadata < P : AsPath > ( path : P ) -> io:: Result < FileAttr > {
37+ path. with_native_path ( fs:: lstat)
38+ }
39+ pub ( crate ) fn metadata < P : AsPath > ( path : P ) -> io:: Result < FileAttr > {
40+ path. with_native_path ( fs:: stat)
41+ }
42+ pub ( crate ) fn rename < P : AsPath , Q : AsPath > ( from : P , to : Q ) -> io:: Result < ( ) > {
43+ from. with_path ( |from| to. with_path ( |to| fs:: rename ( from, to) ) )
44+ }
45+ pub ( crate ) fn hard_link < P : AsPath , Q : AsPath > ( original : P , link : Q ) -> io:: Result < ( ) > {
46+ original. with_path ( |original| link. with_path ( |link| fs:: link ( original, link) ) )
47+ }
48+ pub ( crate ) fn soft_link < P : AsPath , Q : AsPath > ( original : P , link : Q ) -> io:: Result < ( ) > {
49+ original. with_path ( |original| link. with_path ( |link| fs:: symlink ( original, link) ) )
50+ }
51+ pub ( crate ) fn remove_dir < P : AsPath > ( path : P ) -> io:: Result < ( ) > {
52+ path. with_path ( fs:: rmdir)
53+ }
54+ pub ( crate ) fn read_dir < P : AsPath > ( path : P ) -> io:: Result < ReadDir > {
55+ path. with_path ( fs:: readdir)
56+ }
57+ pub ( crate ) fn set_permissions < P : AsPath > ( path : P , perms : FilePermissions ) -> io:: Result < ( ) > {
58+ path. with_path ( |path| fs:: set_perm ( path, perms) )
59+ }
60+ pub ( crate ) fn copy < P : AsPath , Q : AsPath > ( from : P , to : Q ) -> io:: Result < u64 > {
61+ from. with_path ( |from| to. with_path ( |to| fs:: copy ( from, to) ) )
62+ }
63+ pub ( crate ) fn canonicalize < P : AsPath > ( path : P ) -> io:: Result < PathBuf > {
64+ path. with_native_path ( fs:: canonicalize)
65+ }
66+ pub ( crate ) fn remove_dir_all < P : AsPath > ( path : P ) -> io:: Result < ( ) > {
67+ path. with_native_path ( fs:: remove_dir_all)
68+ }
69+ pub ( crate ) fn read_link < P : AsPath > ( path : P ) -> io:: Result < PathBuf > {
70+ path. with_native_path ( fs:: readlink)
71+ }
72+ pub ( crate ) fn try_exists < P : AsPath > ( path : P ) -> io:: Result < bool > {
73+ path. with_native_path ( fs:: try_exists)
74+ }
75+ }
76+
2277pub struct File {
2378 handle : Handle ,
2479}
@@ -294,8 +349,7 @@ impl OpenOptions {
294349}
295350
296351impl File {
297- pub fn open ( path : & Path , opts : & OpenOptions ) -> io:: Result < File > {
298- let path = maybe_verbatim ( path) ?;
352+ pub fn open_native ( path : & NativePath , opts : & OpenOptions ) -> io:: Result < File > {
299353 let creation = opts. get_creation_mode ( ) ?;
300354 let handle = unsafe {
301355 c:: CreateFileW (
@@ -1132,16 +1186,16 @@ pub fn rmdir(p: &Path) -> io::Result<()> {
11321186}
11331187
11341188/// Open a file or directory without following symlinks.
1135- fn open_link ( path : & Path , access_mode : u32 ) -> io:: Result < File > {
1189+ fn open_link ( path : & NativePath , access_mode : u32 ) -> io:: Result < File > {
11361190 let mut opts = OpenOptions :: new ( ) ;
11371191 opts. access_mode ( access_mode) ;
11381192 // `FILE_FLAG_BACKUP_SEMANTICS` allows opening directories.
11391193 // `FILE_FLAG_OPEN_REPARSE_POINT` opens a link instead of its target.
11401194 opts. custom_flags ( c:: FILE_FLAG_BACKUP_SEMANTICS | c:: FILE_FLAG_OPEN_REPARSE_POINT ) ;
1141- File :: open ( path, & opts)
1195+ File :: open_native ( path, & opts)
11421196}
11431197
1144- pub fn remove_dir_all ( path : & Path ) -> io:: Result < ( ) > {
1198+ pub fn remove_dir_all ( path : & NativePath ) -> io:: Result < ( ) > {
11451199 let file = open_link ( path, c:: DELETE | c:: FILE_LIST_DIRECTORY ) ?;
11461200
11471201 // Test if the file is not a directory or a symlink to a directory.
@@ -1241,14 +1295,14 @@ fn remove_dir_all_iterative(f: &File, delete: fn(&File) -> io::Result<()>) -> io
12411295 Ok ( ( ) )
12421296}
12431297
1244- pub fn readlink ( path : & Path ) -> io:: Result < PathBuf > {
1298+ pub fn readlink ( path : & NativePath ) -> io:: Result < PathBuf > {
12451299 // Open the link with no access mode, instead of generic read.
12461300 // By default FILE_LIST_DIRECTORY is denied for the junction "C:\Documents and Settings", so
12471301 // this is needed for a common case.
12481302 let mut opts = OpenOptions :: new ( ) ;
12491303 opts. access_mode ( 0 ) ;
12501304 opts. custom_flags ( c:: FILE_FLAG_OPEN_REPARSE_POINT | c:: FILE_FLAG_BACKUP_SEMANTICS ) ;
1251- let file = File :: open ( path, & opts) ?;
1305+ let file = File :: open_native ( path, & opts) ?;
12521306 file. readlink ( )
12531307}
12541308
@@ -1301,7 +1355,7 @@ pub fn link(_original: &Path, _link: &Path) -> io::Result<()> {
13011355 ) ) ;
13021356}
13031357
1304- pub fn stat ( path : & Path ) -> io:: Result < FileAttr > {
1358+ pub fn stat ( path : & NativePath ) -> io:: Result < FileAttr > {
13051359 match metadata ( path, ReparsePoint :: Follow ) {
13061360 Err ( err) if err. raw_os_error ( ) == Some ( c:: ERROR_CANT_ACCESS_FILE as i32 ) => {
13071361 if let Ok ( attrs) = lstat ( path) {
@@ -1315,7 +1369,7 @@ pub fn stat(path: &Path) -> io::Result<FileAttr> {
13151369 }
13161370}
13171371
1318- pub fn lstat ( path : & Path ) -> io:: Result < FileAttr > {
1372+ pub fn lstat ( path : & NativePath ) -> io:: Result < FileAttr > {
13191373 metadata ( path, ReparsePoint :: Open )
13201374}
13211375
@@ -1331,7 +1385,7 @@ impl ReparsePoint {
13311385 }
13321386}
13331387
1334- fn metadata ( path : & Path , reparse : ReparsePoint ) -> io:: Result < FileAttr > {
1388+ fn metadata ( path : & NativePath , reparse : ReparsePoint ) -> io:: Result < FileAttr > {
13351389 let mut opts = OpenOptions :: new ( ) ;
13361390 // No read or write permissions are necessary
13371391 opts. access_mode ( 0 ) ;
@@ -1340,7 +1394,7 @@ fn metadata(path: &Path, reparse: ReparsePoint) -> io::Result<FileAttr> {
13401394 // Attempt to open the file normally.
13411395 // If that fails with `ERROR_SHARING_VIOLATION` then retry using `FindFirstFileW`.
13421396 // If the fallback fails for any reason we return the original error.
1343- match File :: open ( path, & opts) {
1397+ match File :: open_native ( path, & opts) {
13441398 Ok ( file) => file. file_attr ( ) ,
13451399 Err ( e)
13461400 if [ Some ( c:: ERROR_SHARING_VIOLATION as _ ) , Some ( c:: ERROR_ACCESS_DENIED as _ ) ]
@@ -1353,8 +1407,6 @@ fn metadata(path: &Path, reparse: ReparsePoint) -> io::Result<FileAttr> {
13531407 // However, there are special system files, such as
13541408 // `C:\hiberfil.sys`, that are locked in a way that denies even that.
13551409 unsafe {
1356- let path = maybe_verbatim ( path) ?;
1357-
13581410 // `FindFirstFileW` accepts wildcard file names.
13591411 // Fortunately wildcards are not valid file names and
13601412 // `ERROR_SHARING_VIOLATION` means the file exists (but is locked)
@@ -1403,13 +1455,13 @@ fn get_path(f: &File) -> io::Result<PathBuf> {
14031455 )
14041456}
14051457
1406- pub fn canonicalize ( p : & Path ) -> io:: Result < PathBuf > {
1458+ pub fn canonicalize ( p : & NativePath ) -> io:: Result < PathBuf > {
14071459 let mut opts = OpenOptions :: new ( ) ;
14081460 // No read or write permissions are necessary
14091461 opts. access_mode ( 0 ) ;
14101462 // This flag is so we can open directories too
14111463 opts. custom_flags ( c:: FILE_FLAG_BACKUP_SEMANTICS ) ;
1412- let f = File :: open ( p, & opts) ?;
1464+ let f = File :: open_native ( p, & opts) ?;
14131465 get_path ( & f)
14141466}
14151467
@@ -1467,7 +1519,7 @@ fn symlink_junction_inner(original: &Path, junction: &Path) -> io::Result<()> {
14671519 let mut opts = OpenOptions :: new ( ) ;
14681520 opts. write ( true ) ;
14691521 opts. custom_flags ( c:: FILE_FLAG_OPEN_REPARSE_POINT | c:: FILE_FLAG_BACKUP_SEMANTICS ) ;
1470- let f = File :: open ( junction, & opts) ?;
1522+ let f = File :: open_native ( & maybe_verbatim ( junction) ? , & opts) ?;
14711523 let h = f. as_inner ( ) . as_raw_handle ( ) ;
14721524 unsafe {
14731525 let mut data =
@@ -1525,14 +1577,14 @@ fn symlink_junction_inner(original: &Path, junction: &Path) -> io::Result<()> {
15251577}
15261578
15271579// Try to see if a file exists but, unlike `exists`, report I/O errors.
1528- pub fn try_exists ( path : & Path ) -> io:: Result < bool > {
1580+ pub fn try_exists ( path : & NativePath ) -> io:: Result < bool > {
15291581 // Open the file to ensure any symlinks are followed to their target.
15301582 let mut opts = OpenOptions :: new ( ) ;
15311583 // No read, write, etc access rights are needed.
15321584 opts. access_mode ( 0 ) ;
15331585 // Backup semantics enables opening directories as well as files.
15341586 opts. custom_flags ( c:: FILE_FLAG_BACKUP_SEMANTICS ) ;
1535- match File :: open ( path, & opts) {
1587+ match File :: open_native ( path, & opts) {
15361588 Err ( e) => match e. kind ( ) {
15371589 // The file definitely does not exist
15381590 io:: ErrorKind :: NotFound => Ok ( false ) ,
0 commit comments